zzz

Noritake.cpp

Committer:
mauuuuul
Date:
2020-08-26
Revision:
0:530fa614d79a

File content as of revision 0:530fa614d79a:

#include "mbed.h"
#include "Noritake.h"
#include <string.h>

Noritake::Noritake(PinName tx, PinName rx):VFDSerial(tx, rx)
{
    VFDSerial.baud(NORITAKE_BAUD_DEF);
}

Noritake::~Noritake()
{
    
}

void Noritake::writePort(uint8_t data)
{
    VFDSerial.putc(data);
}
void Noritake::hardReset()
{
    VFDSerial.putc(0x0c);
    wait_ms(200);
    VFDSerial.putc(0x1f);
    VFDSerial.putc(0x24);
    VFDSerial.putc(0x00);
    VFDSerial.putc(0x00);
    VFDSerial.putc(0x00);
    VFDSerial.putc(0x00);
}

void Noritake::GU7000_back() {
    command(0x08);
}

void Noritake::GU7000_forward() {
    command(0x09);
}

void Noritake::GU7000_lineFeed() {
    command(0x0a);
}

void Noritake::GU7000_home() {
    command(0x0b);
}

void Noritake::GU7000_carriageReturn() {
    command(0x0d);
}

void Noritake::GU7000_setCursor(unsigned x, unsigned y) {
    command(0x1f);
    command('$');
    command_xy(x, y);
}

void Noritake::GU7000_clearScreen() {
    command(0x0c);
}

void Noritake::GU7000_cursorOn() {
    command(0x1f, 'C', 1);
}

void Noritake::GU7000_cursorOff() {
    command(0x1f, 'C', 0);
}

void Noritake::GU7000_init() {
    wait_us(NORITAKE_VFD_RESET_DELAY);
    command(0x1b);
    command('@');
}

void Noritake::GU7000_reset() {
    hardReset();
}

void Noritake::GU7000_useMultibyteChars(bool enable) {
    #if (NORITAKE_VFD_MODEL_CLASS-7000)/100==9 || (NORITAKE_VFD_MODEL_CLASS-7000)/100==1
        us_command('g', 0x02);
        command(enable);
    #endif
}

void Noritake::GU7000_setMultibyteCharset(uint8_t code) {
    #if (NORITAKE_VFD_MODEL_CLASS-7000)/100==9 || (NORITAKE_VFD_MODEL_CLASS-7000)/100==1
        us_command('g', 0x0f);
        command(code);
    #endif
}

void Noritake::GU7000_useCustomChars(bool enable) {
    command(0x1b, '%', enable);
}

static inline uint8_t getColumn(const uint8_t *src, int col) {
    uint8_t out = 0;
    for (int i=0; i<8; i++)
        if (src[i] & (1<<(4-col))) out += 1<<(7-i);
    return out;
}

void Noritake::GU7000_defineCustomChar(uint8_t code, FontFormat format, const uint8_t *data) {
    command(0x1b, '&', 0x01);
    command(code);
    command(code);
    
    switch (format) {
    case CUUFormat:
        command(5);
        for (uint8_t i=0; i<5; i++)
            command(getColumn(data, i));
        break;
    
    case GU70005x7Format:
        command(5);
        print((const char*)data, 5);
        break;
    case GU70007x8Format:
        command(7);
        print((const char*)data, 7);
        break;
    }
}

void Noritake::GU7000_deleteCustomChar(uint8_t code) {
    command(0x01b, '?', 0x01);
    command(code);
}

void Noritake::GU7000_setAsciiVariant(AsciiVariant code) {
    command(0x1b, 'R', code);
}

void Noritake::GU7000_setCharset(Charset code) {
    command(0x1b, 't', code);
}

void Noritake::GU7000_setScrollMode(ScrollMode mode) {
    command(0x1f);
    command(mode);
}

void Noritake::GU7000_setHorizScrollSpeed(uint8_t speed) {
    command(0x1f, 's', speed);
}

void Noritake::GU7000_invertOff() {
    command(0x1f, 'r', 0);
}

void Noritake::GU7000_invertOn() {
    command(0x1f, 'r', 1);
}

void Noritake::GU7000_setCompositionMode(CompositionMode mode) {
    command(0x1f, 'w', mode);
}

void Noritake::GU7000_setScreenBrightness(unsigned level) {
    if (level == 0)
        GU7000_displayOff();
    else if (level <= 100) {
        GU7000_displayOn();
        command(0x1f, 'X', (level*10 + 120)/125);
    }
}

void Noritake::GU7000_wait(uint8_t time) {
    us_command('a', 0x01);
    command(time);
}

void Noritake::GU7000_scrollScreen(unsigned x, unsigned y, unsigned times, uint8_t speed) {
    unsigned pos = (x*NORITAKE_VFD_LINES)+(y/8);
    us_command('a', 0x10);
    command(pos);
    command(pos>>8);
    command(times);
    command(times>>8);
    command(speed);
}

void Noritake::GU7000_blinkScreen() {
    us_command('a', 0x11);
    command(0);
    command(0);
    command(0);
    command(0);
}

void Noritake::GU7000_blinkScreen(bool enable, bool reverse, uint8_t onTime, uint8_t offTime, uint8_t times) {
    us_command('a', 0x11);
    command(enable? (reverse? 2: 1): 0);
    command(onTime);
    command(offTime);
    command(times);
}

void Noritake::GU7000_displayOff() {
    us_command('a', 0x40);
    command(0);
}

void Noritake::GU7000_displayOn() {
    us_command('a', 0x40);
    command(0x01);
}

void Noritake::GU7000_screenSaver(ScreenSaver mode) {
    us_command('a', 0x40);
    command(mode);
}

void Noritake::GU7000_setFontStyle(bool proportional, bool evenSpacing) {
    us_command('g', 0x03);
    command(proportional*2 + evenSpacing);
}

void Noritake::GU7000_setFontSize(uint8_t x, uint8_t y, bool tall) {
    if (x<=4 && y<=4) {        
        us_command('g', 0x40);
        command(x);
        command(y);
        #if (NORITAKE_VFD_MODEL_CLASS-7000)/100==9 || (NORITAKE_VFD_MODEL_CLASS-7000)/100==1
            us_command('g', 0x01);
            command(tall+1);
        #endif
    }
}

void Noritake::GU7000_selectWindow(uint8_t window) {
    if (window <= 4)
        command(0x10 + window);
}

void Noritake::GU7000_defineWindow(uint8_t window, unsigned x, unsigned y, unsigned width, unsigned height) {
    us_command('w', 0x02);
    command(window);
    command(0x01);
    command_xy(x, y);
    command_xy(width, height);
}

void Noritake::GU7000_deleteWindow(uint8_t window) {
    us_command('w', 0x02);
    command(window);
    command(0);
    command_xy(0, 0);
    command_xy(0, 0);
}

void Noritake::GU7000_joinScreens() {
    us_command('w', 0x10);
    command(0x01);
}

void Noritake::GU7000_separateScreens() {
    us_command('w', 0x10);
    command(0);
}

void Noritake::print(char c) {
    command(c);
}

void Noritake::print(const char *str, ...) {
    while (*str)
        writePort(*str++);
}

void Noritake::print(const char *buffer, size_t size) {
    while (size--)
        print(*buffer++);
}

void Noritake::print(long number, uint8_t base) {
    if (number < 0) {
        print('-');
        number = -number;
    }
    printNumber(number, base);
}

void Noritake::print(int number, uint8_t base) {
    print((long)number, base);
}

void Noritake::print(unsigned long number, uint8_t base) {
    printNumber(number, base);
}

void Noritake::print(unsigned number, uint8_t base) {
    print((unsigned long)number, base);
}

void Noritake::printat(unsigned x, uint8_t y, const char *str)
{
    GU7000_setCursor(x, y);
    print(str);
}

void Noritake::crlf() {
    GU7000_carriageReturn();
    GU7000_lineFeed();
}

void Noritake::println(char c) {
    print(c);
    crlf();
}

void Noritake::println(const char *str) {
    print(str);
    crlf();
}

void Noritake::println(const char *buffer, size_t size) {
    print(buffer, size);
    crlf();
}

void Noritake::println(long number, uint8_t base) {
    print(number, base);
    crlf();
}

void Noritake::println(int number, uint8_t base) {
    println((long) number, base);
}

void Noritake::println(unsigned long number, uint8_t base) {
    print(number, base);
    crlf();
}

void Noritake::println(unsigned number, uint8_t base) {
    println((unsigned long) number, base);
}

void Noritake::printNumber(unsigned long number, uint8_t base) {
    if (number/base)
        printNumber(number/base, base);
    number %= base;
    print(number + (number < 10? '0': 'A' - 10));
}

void Noritake::GU7000_setBacklightColor(uint8_t r, uint8_t g, uint8_t b) {
    #if NORITAKE_VFD_MODEL_CLASS==7040
        command(0x1f, 'L', 0x10);
        command(b & 0xf0);
        command(g & 0xf0);
        command(r & 0xf0);
    #endif
}

void Noritake::GU7000_setBacklightColor(unsigned rgb) {
    GU7000_setBacklightColor((rgb>>8 & 0x0f)*16, (rgb>>4 & 0x0f)*16, (rgb & 0x0f)*16);
}

void Noritake::GU7000_drawImage(unsigned width, uint8_t height, const uint8_t *data) {
    if (height > NORITAKE_VFD_HEIGHT) return;
    us_command('f', 0x11);
    command_xy(width, height);
    command((uint8_t) 1);
    for (unsigned i = 0; i<(height/8)*width; i++)
        command(data[i]);
}

void Noritake::GU7000_drawFROMImage(unsigned long address, uint8_t srcHeight, unsigned width, uint8_t height) {
    #if (NORITAKE_VFD_MODEL_CLASS-7000)/100==9 || (NORITAKE_VFD_MODEL_CLASS-7000)/100==1        
        if (height > NORITAKE_VFD_HEIGHT) return;
        us_command('f', 0x10);
        command(0x01);
        command(address);
        command(address>>8);
        command(address>>16);
        command(srcHeight/8);
        command((srcHeight/8)>>8);
        command_xy(width, height);
        command((uint8_t) 1);
    #endif
}

static unsigned min(unsigned x, unsigned y) { return x<y? x: y; }

void Noritake::GU7000_fillRect(unsigned x0, unsigned y0, unsigned x1, unsigned y1, bool on) {
    x0 = min(NORITAKE_VFD_WIDTH, x0);
    x1 = min(NORITAKE_VFD_WIDTH, x1);
    y0 = min(NORITAKE_VFD_HEIGHT, y0);
    y1 = min(NORITAKE_VFD_HEIGHT, y1);
    if (y1<=y0 || x1<=x0) return;
    uint8_t bufw = 8, bufh = (y1-y0+7)/8*8;
    uint8_t *buf = (uint8_t*) malloc(bufh/8 * bufw);
    for (unsigned x = 0; x < x1-x0; x += bufw) {
        uint8_t part = (x + bufw < x1-x0)? bufw: (x1-x0) - x;
        memset(buf, 0, bufh/8 * bufw);
        if (on)
            for (uint8_t col = 0; col < part; col++) {
                for (uint8_t py = y0 % 8; py < y0 % 8 + min(y1-y0, 8); py++)
                    buf[col*bufh/8] |= 1 << (7-py);
                for (uint8_t row = (y0+7)/8; row < y1/8; row++)
                    buf[row - y0/8 + col*bufh/8] = 0xff;
                if (y0/8 != y1/8)
                    for (uint8_t py = 0; py < y1 % 8; py++)
                        buf[(y1-y0)/8 + col*bufh/8] |= 1 << (7-py);
            }
        GU7000_setCursor(x + x0, y0);
        GU7000_drawImage(bufw, bufh, buf);
    }
}

void Noritake::command(uint8_t data) {
//    writePort(data);
    VFDSerial.putc(data);
}
void Noritake::command_xy(unsigned x, unsigned y) {
    command(x);
    command(x>>8);
    y /= 8;
    command(y);
    command(y>>8);
}
void Noritake::command_xy1(unsigned x, unsigned y) {
    command(x);
    command(x>>8);
    command(y);
    command(y>>8);
}

void Noritake::us_command(uint8_t group, uint8_t cmd) {
   command(0x1f);
   command(0x28);
   command(group);
   command(cmd);
}

void Noritake::command(uint8_t prefix, uint8_t group, uint8_t cmd) {
   command(prefix);
   command(group);
   command(cmd);
}

void Noritake::print(unsigned x, uint8_t y, const char *buffer, uint8_t len) {
    #if NORITAKE_VFD_GENERATION == 'B'
        us_command('d', 0x30);
        command_xy1(x, y);
        command(0);
        command(len);
        while (len--)
            command(*buffer++);
    #endif
}

void Noritake::print(unsigned x, uint8_t y, const char *str) {
    #if NORITAKE_VFD_GENERATION == 'B'
        print(x, y, str, strlen(str));
    #endif
}
void Noritake::print(unsigned x, uint8_t y, char c) {
    #if NORITAKE_VFD_GENERATION == 'B'
        print(x, y, &c, 1);
    #endif
}
void Noritake::print(unsigned x, uint8_t y, int number, uint8_t base) {
    #if NORITAKE_VFD_GENERATION == 'B'
        if (number < 0) {
            print(x, y, '-');
            print(-1, y, (unsigned)-number, base);        
        } else
            print(x, y, (unsigned)number, base);
    #endif
}
void Noritake::print(unsigned x, uint8_t y, unsigned number, uint8_t base) {
    #if NORITAKE_VFD_GENERATION == 'B'
        char buf[16], *p = buf + sizeof buf;
        do
            *--p = number % base + (number % base < 10? '0': 'A' - 10);
        while (number /= base);
        print(x, y, p, buf + sizeof buf - p);
    #endif
}
void Noritake::GU7000_drawImage(unsigned x, uint8_t y, unsigned width, uint8_t height, const char *data) {
    #if NORITAKE_VFD_GENERATION == 'B'
        us_command('d', 0x21);
        command_xy1(x, y);
        command_xy1(width, height);
        command(0x01);
        for (unsigned i = 0; i<(height/8)*width; i++)
            command(data[i]);
    #endif
}
void Noritake::GU7000_drawImage(unsigned x, uint8_t y, ImageMemoryArea area, unsigned long address, uint8_t srcHeight, unsigned width, uint8_t height, unsigned offsetx, unsigned offsety) {
    #if NORITAKE_VFD_GENERATION == 'B'
        if (height > NORITAKE_VFD_HEIGHT) return;
        us_command('d', 0x20);
        command_xy1(x, y);
        command(area);
        command(address);
        command(address>>8);
        command(address>>16);
        command(srcHeight/8);
        command(srcHeight/8>>8);
        command_xy1(offsetx, offsety);
        command_xy1(width, height);
        command(0x01);
    #endif
}

void Noritake::GU7000_drawImage(unsigned x, uint8_t y, ImageMemoryArea area, unsigned long address, unsigned width, uint8_t height) {
    #if NORITAKE_VFD_GENERATION == 'B'
        GU7000_drawImage(x, y, area, address, (height + 7) & ~7, width, height, 0, 0);
    #endif
}

void Noritake::print_p(const char *str) {
    while (pgm_read_byte(str))
        writePort(pgm_read_byte(str++));
}
void Noritake::print_p(unsigned x, uint8_t y, const char *buffer, uint8_t len) {
    #if NORITAKE_VFD_GENERATION == 'B'
        us_command('d', 0x30);
        command_xy1(x, y);
        command(0);
        command(len);
        while (len--)
            command(pgm_read_byte(buffer++));
    #endif
}

void Noritake::print_p(unsigned x, uint8_t y, const char *str) {
    #if NORITAKE_VFD_GENERATION == 'B'
        const char *end = str;
        while (pgm_read_byte(end)) end++;
        print_p(x, y, str, end - str);
    #endif
}

void Noritake::GU7000_drawImage_p(unsigned width, uint8_t height, const uint8_t *data) {
    if (height > NORITAKE_VFD_HEIGHT) return;
    us_command('f', 0x11);
    command_xy(width, height);
    command((uint8_t) 1);
    for (unsigned i = 0; i<(height/8)*width; i++)
        command(pgm_read_byte(data+i));
}

void Noritake::GU7000_drawImage_p(unsigned x, uint8_t y, unsigned width, uint8_t height, const uint8_t *data) {
    #if NORITAKE_VFD_GENERATION == 'B'
        us_command('d', 0x21);
        command_xy1(x, y);
        command_xy1(width, height);
        command(0x01);
        for (unsigned i = 0; i<(height/8)*width; i++)
            command(pgm_read_byte(data+i));
    #endif
}