The London Hackspace Bandwidth meter, now works over ethernet.

Dependencies:   EthernetInterface LPD8806 Tiny-HTTPD mbed-rtos mbed BonjourLib

vfd.cpp

Committer:
Jasper
Date:
2014-05-30
Revision:
4:d522cfa6e410
Parent:
0:0e7057b49904

File content as of revision 4:d522cfa6e410:

/*
 * The VFD code
 *
 * for a futuba M204LD01AA
 * 
 *
 * p27 -> input, busy
 * p28 -> serial data in
 * p29 -> clock 
 * p30 -> latch
 *
 *
 */

#include "mbed.h"
#include "vfd.h"
//#include "Stream.h"
//#include "FunctionPointer.h"

// InturruptIn busy_intr(p27)

DigitalIn  vfd_p_busy(p27);
DigitalOut vfd_p_data(p28);
DigitalOut vfd_p_clock(p29);
DigitalOut vfd_p_latch(p30);

/* current state */
int  c_data;
bool c_a0;
bool c_blank;

bool vfd_dead = 0;

void vfd_shift_clock(void) {
        vfd_p_clock = 0;
        wait_us(10);
        vfd_p_clock = 1;
        wait_us(10);
}

void vfd_doit(int data, int mode, int wr, int ss, int reset) {
    int i, bit;
    
    vfd_p_data = 0; // nc
    vfd_shift_clock();
    vfd_p_data = 0; // nc
    vfd_shift_clock();

    vfd_p_data = reset; // reset, 0 = in reset
    vfd_shift_clock();

    vfd_p_data = c_blank; // Blank, 0 = blanked
    vfd_shift_clock();
    
    vfd_p_data = ss; // SS, clockish
    vfd_shift_clock();

    vfd_p_data = 1; // rd
    vfd_shift_clock();

    vfd_p_data = mode; // A0, data/command
    vfd_shift_clock();

    vfd_p_data = wr; // WR
    vfd_shift_clock();

    for (i = 0 ; i < 8; i++) {
        bit = (data & (1 << i)) >> i;
        vfd_p_data = bit;
        vfd_shift_clock();
    }
        
    vfd_p_latch = 0;
    wait_us(10);
    vfd_p_latch = 1;
    wait_us(10);
}

/* mode == 1 if command */
void vfd_send(int data, int mode, int force)
{
    data = data & 0xff;
    c_data = data;
    c_blank = 1;

//    if (mode == 0)
//        printf("%02x ", data);

    if (vfd_dead && ! force) {
        printf("vfd dead (?), not sending.\r\n");
        return;
    }
    if (force)
        printf("forcing vfd for 0x%02x %d\r\n", data, mode);

    if (vfd_p_busy) {
        printf("pre, busy: %d\r\n", vfd_p_busy.read());
    }
    
    if (vfd_p_busy)
    {
        wait_ms(4); // should loop, 3.1 ms is max according to the data sheet.
        if (vfd_p_busy)
        {
            printf("still busy :(\r\n");
            printf("resetting\r\n");
            if (!force)
                vfd_reset();
            if (vfd_p_busy) {
                printf("still busy after reset!\r\n");
                if (!force)
                    return;
            }
            if (!force)
                return;
        }
    }
    
    /* wr,ss */
    vfd_doit(data, mode, 0, 0, 1);
    wait_us(1);
    vfd_doit(data, mode, 1, 0, 1);
    wait_us(1);
    vfd_doit(data, mode, 1, 1, 1);
    wait_us(1);

    if (vfd_p_busy)
        printf("post1, busy: %d\r\n", vfd_p_busy.read());

    vfd_doit(data, mode, 0, 0, 1);

    if (vfd_p_busy)
        printf("post2, busy: %d\r\n", vfd_p_busy.read());

    // loop and wait for not busy
    while (vfd_p_busy) {
        wait_us(250);
        printf("post-while, busy: %d\r\n", vfd_p_busy.read());
    }
}

void vfd_command(int data, int force) {
    vfd_send(data, 1, force);
}

void vfd_data(int data) {
    if ((data & 0xff) == 0x7f) {
        data = 0x20;
        printf("changed data to %02x\r\n", data);
    }
    vfd_send(data, 0, 0);
}

void vfd_init(void) {
    vfd_data(0x11); // normal mode
    vfd_data(0x0c); // clear
    vfd_data(0x1b); // esc
    vfd_data(0);    // v pos
    vfd_data(0);    // h pos
}

void vfd_blank(void) {
    /* blank */
}

void vfd_show(void) {
    /* unblank */
}

void vfd_pos(int h, int v) {
    if (v > 3 || v < 0)
        return;
    if (h > 19 || h < 0)
        return;
    vfd_data(0x1b);
    vfd_data(v);
    vfd_data(h);
}

void vfd_reset(void) {
    int i, data, mode;

    data = 0; mode = 1;

    printf("reset sent, busy: %d\r\n", vfd_p_busy.read());

    /* everything low, includeing reset */
    for (i = 0 ; i < 16; i++) {
        vfd_p_data = 0;
        vfd_shift_clock();
    }
    vfd_p_latch = 0;
    wait_us(10);
    vfd_p_latch = 1;

    vfd_doit(data, mode, 0, 0, 1);
    wait_us(1);
    vfd_doit(data, mode, 1, 0, 1);
    wait_us(1);
    vfd_doit(data, mode, 1, 1, 1);
    wait_us(1);

    if (vfd_p_busy)
        printf("post1, busy: %d\r\n", vfd_p_busy.read());

    vfd_doit(data, mode, 0, 0, 1);
    wait_ms(4); // loop and wait for not busy

    printf("reset sent, busy: %d\r\n", vfd_p_busy.read());
    wait_ms(10);
    if (vfd_p_busy) {
        printf("still busy, not calling vfd_init()\r\n");
        vfd_reset_cmd();
        printf("post reset_cmd\r\n");
        if (vfd_p_busy) {
            printf("Also still busy, marking as dead\r\n");
            vfd_dead = 1;
        } else {
            vfd_init();    
        }
        wait_ms(10);
    } else {
        if (!vfd_dead)
            vfd_init();
    }
}

void vfd_reset_cmd(void) {
    vfd_command(0xff, 1);
}

void send_text(const char *s) {
    int i; char c;

    for (i = 0, c=s[i]; c != 0;  i++, c=s[i])
        vfd_data(c);
}

void text_centered(const char *s, int hpos) {

    vfd_pos((20 / 2) - (strlen(s)) / 2, hpos);
    send_text(s);
}

void logo(void) {
    const char line0[] = "Welcome to";
    const char line2[] = "London Hackspace";

    text_centered(line0, 0);
    text_centered(line2, 2);        
}

/*
class Vfd : Public Stream {
    public:
    
        
}
*/