Driving VFD panels with PT6311 controller

Rafael
Posts: 12
Joined: Tue Mar 25, 2014 4:23 pm

Re: Driving VFD panels with PT6311 controller

Postby Rafael » Thu Apr 21, 2016 12:45 pm

Hi Dmitry,

Yes, I know, I am trying:

Sketch:

Code: Select all

  vfd.reset();
  vfd.displayOnCmd(VFD_DIMMING_MAX);
  vfd.print_f_p("0");


Charset20S.h

Code: Select all

const PROGMEM uint8_t FONT_PGM[63][2] = {
    {0x00,0x00}, // space 0x20
    {0xC0,0x60}, // ! -: (bits 15, 14, 6, 5)
    {0x00,0x00}, // " N/A
    {0x00,0x00}, // # N/A
    {0xE3,0x51}, // $ (bits 15, 14, 13, 9, 8, 6, 4, 0)
    {0x00,0x00}, // % N/A
    {0x00,0x00}, // & N/A
    {0x00,0x00}, // ' N/A
    {0x04,0x04}, // ( (bits 10, 2)
    {0x08,0x08}, // ) (bits 11, 3)
    {0xCE,0x4C}, // * (bits 15, 14, 11, 10, 9, 6, 3, 2)
    {0xC2,0x40}, // + (bits 15, 14, 9, 6)
    {0x00,0x00}, // , N/A
    {0xC0,0x40}, // - (bits 15, 14, 6)
    {0x00,0x40}, // . (bit 6)
    {0x08,0x44}, // / (bits 11, 6, 2)
    {0xFF,0xFF}, // 0 (bits 13, 12, 11, 8, 6, 4, 2, 1, 0) //FF to see all segments on.
    {0x20,0x6},  // 1 (bits 13, 2, 1)
    {0x89,0x52}, // 2 (bits 15, 11, 8, 6, 4, 1)
    {0x05,0x54}, // 3 (bits 10, 8, 6, 4, 2)
    ...
    ...


VFDPanel_20S8D.cpp

Code: Select all

uint8_t VFD_20S8D::write(uint8_t* buffer, uint8_t dstIndex, uint8_t len)
{
    if (len == 0 || (dstIndex >= VFD_DIGITS * VFD_BYTES_PER_DIGIT)) return 0;
    if (len > VFD_DIGITS * VFD_BYTES_PER_DIGIT - dstIndex)
        len = VFD_DIGITS * VFD_BYTES_PER_DIGIT - dstIndex;

    driver.addrSetCmd(dstIndex);

    driver.displayMemWriteCmd(true, false);
    for (uint8_t i = 0; i < len-1; i++)
    {
         driver.data(buffer[i], false, false);
    }
    driver.data(buffer[len-1], false, true);

    return len;
}

uint8_t VFD_20S8D::write_f(uint8_t* buffer, uint8_t dstIndex, uint8_t len)
{
    if (len == 0 || (dstIndex >= VFD_DIGITS * VFD_BYTES_PER_DIGIT)) return 0;
    if (len > VFD_DIGITS * VFD_BYTES_PER_DIGIT - dstIndex)
        len = VFD_DIGITS * VFD_BYTES_PER_DIGIT - dstIndex;

    memcpy(&_vfdFrame[dstIndex], buffer, len);

    return len;
}

void VFD_20S8D::print_f_p(const prog_char str[])
{
    char c;
    uint8_t idx = 0;
    if(!str) return;

    //clearFrame();
   
    while((c = pgm_read_byte(str++)))
    {
        write_f(c, idx, false);
        idx += VFD_BYTES_PER_DIGIT;
    }
}


Still no success.

Thanks.

User avatar
dmitryp
Site Admin
Posts: 45
Joined: Sun Aug 04, 2013 1:16 am
Location: Sydney, Australia
Contact:

Re: Driving VFD panels with PT6311 controller

Postby dmitryp » Fri Apr 22, 2016 12:32 am

Hi Rafael,

I don't see how you initialise pins. Also, print_f_p renders data to internal RAM buffer, to do physical data transfer to the VFD controller you need to invoke flipFrame(), see below:

Code: Select all

  vfd.init(VFD_CS_PIN, VFD_CLK_PIN, VFD_DATA_PIN);
  vfd.reset();
  vfd.clearFrame();
  vfd.print_f_p("0");
  vfd.flipFrame(); 


where vfd is instance of VFD_19S9D class (just to make sure that we are talking about the same thing)

Thank you,
Dmitry

Rafael
Posts: 12
Joined: Tue Mar 25, 2014 4:23 pm

Re: Driving VFD panels with PT6311 controller

Postby Rafael » Fri Apr 22, 2016 10:02 pm

Success!! :)

Sketch:

Code: Select all

#include <util/delay.h>
#include <VFDPanel_20S8D.h>

#define VFD_CS_PIN 2   //Just an example, specify your own correct pin number! This is STB in PT6311 datasheet notation.
#define VFD_CLK_PIN 3  //Just an example, specify your own correct pin number! This is CLK in PT6311 datasheet notation.
#define VFD_DATA_PIN 4 //Just an example, specify your own correct pin number! This is DIN in PT6311 datasheet notation.

VFD_20S8D vfd(VFD_CS_PIN, VFD_CLK_PIN, VFD_DATA_PIN);

void setup()
{
  vfd.reset();
  vfd.clearFrame();
  vfd.print_f_p(PSTR("0"));
  vfd.flipFrame(); 
}

void loop()

}


Charset20S.h

Code: Select all

#ifndef CHARSET20S_H
#define CHARSET20S_H

#include "settings.h"

const PROGMEM uint8_t SCROL_FRAMES[3][14] =
    {
        {
        0x01, 0x10, //bits 8, 4
        0x00, 0x00, //bits -
        0x00, 0x00, //bits -
        0x01, 0x10, //bits 8, 4
        0x00, 0x00, //bits -
        0x00, 0x00, //bits -
        0x01, 0x10, //bits 8, 4
        },
        {
        0x00, 0x01, //bits 0
        0x01, 0x00, //bits 8
        0x00, 0x10, //bits 4
        0x00, 0x00, //bits -
        0x01, 0x00, //bits 8
        0x00, 0x10, //bits 4
        0x20, 0x00, //bits 13
        },
        {
        0x10, 0x00, //bits 12
        0x00, 0x10, //bits 4
        0x01, 0x00, //bits 8
        0x00, 0x00, //bits -
        0x00, 0x10, //bits 4
        0x01, 0x00, //bits 8
        0x00, 0x02, //bits 1
        }
    };

const PROGMEM uint8_t ROTOR_PGM[4][2] = {
    {0x02,0x40}, // | (bits 9, 6)
    {0x04,0x48}, // \ (bits 10, 6, 3)
    {0xC0,0x40}, // - (bits 15, 14, 6)
    {0x08,0x44}  // / (bits 11, 6, 2)
};

const PROGMEM uint8_t FONT_PGM[63][2] = {
    {0x00,0x00}, // space 0x20
    {0xC0,0x60}, // ! -: (bits 15, 14, 6, 5)
    {0x00,0x00}, // " N/A
    {0x00,0x00}, // # N/A
    {0xE3,0x51}, // $ (bits 15, 14, 13, 9, 8, 6, 4, 0)
    {0x00,0x00}, // % N/A
    {0x00,0x00}, // & N/A
    {0x00,0x00}, // ' N/A
    {0x04,0x04}, // ( (bits 10, 2)
    {0x08,0x08}, // ) (bits 11, 3)
    {0xCE,0x4C}, // * (bits 15, 14, 11, 10, 9, 6, 3, 2)
    {0xC2,0x40}, // + (bits 15, 14, 9, 6)
    {0x00,0x00}, // , N/A
    {0xC0,0x40}, // - (bits 15, 14, 6)
    {0x00,0x40}, // . (bit 6)
    {0x08,0x44}, // / (bits 11, 6, 2)
    {0xFF,0xFF}, // 0 (bits 13, 12, 11, 8, 6, 4, 2, 1, 0)
    {0x20,0x6},  // 1 (bits 13, 2, 1)
    {0x89,0x52}, // 2 (bits 15, 11, 8, 6, 4, 1)
    {0x05,0x54}, // 3 (bits 10, 8, 6, 4, 2)
    {0xC2,0x41}, // 4 (bits 15, 14, 9, 6, 0)
    {0xE1,0x51}, // 5 (bits 15, 14, 13, 8, 6, 4, 0)
    {0xF1,0x51}, // 6 (bits bits 15, 14, 13, 12, 8, 6, 4, 0)
    {0x08,0x54}, // 7 (bits 11, 6, 4, 2)
    {0xF1,0x53}, // 8 (bits 15, 14, 13, 12, 8, 6, 4, 1, 0)
    {0xE1,0x53}, // 9 (bits 15, 14, 13, 8, 6, 4, 1, 0)
    {0x00,0x20}, // : (bit 5)
    {0x00,0x00}, // ; N/A
    {0x04,0x04}, // < (bits 10, 2)
    {0x00,0x00}, // = N/A
    {0x08,0x08}, // > (bits 11, 3)
    {0x00,0x00}, // ? N/A
    {0x00,0x00}, // @ N/A
    {0xF0,0x53}, // A (bits 15, 14, 13, 12, 6, 4, 1, 0)
    {0xA3,0x52}, // B (bits 15, 13, 9, 8, 6, 4, 1 )
    {0x11,0x11}, // C (bits 12, 8, 4, 0)
    {0x23,0x52}, // D (bits 13, 9, 8, 6, 4, 1 )
    {0xD1,0x51}, // E (bits 15, 14, 12, 8, 6, 4, 0)
    {0x50,0x51}, // F (bits 14, 12, 6, 4, 0)
    {0xB1,0x11}, // G (bits 15, 13, 12, 8, 4, 0)
    {0xF0,0x43}, // H (bits 15, 14, 13, 12, 6, 1, 0)
    {0x02,0x40}, // I (bits 9, 6)
    {0x31,0x02}, // J (bits 13, 12, 8, 1)
    {0x54,0x45}, // K (bits 14, 12, 10, 6, 2, 0)
    {0x11,0x01}, // L (bits 12, 8, 0)
    {0x30,0x4F}, // M (bits 13, 12, 6, 3, 2, 1, 0)
    {0x34,0x4B}, // N (bits 13, 12, 10, 6, 3, 1, 0)
    {0x31,0x13}, // O (bits 13, 12, 8, 4, 1, 0)
    {0xD0,0x53}, // P (bits 15, 14, 12, 6, 4, 1, 0)
    {0x35,0x13}, // Q (bits 13, 12, 10, 8, 4, 1, 0)
    {0xD4,0x53}, // R (bits 15, 14, 12, 10, 6, 4, 1, 0)
    {0xE1,0x51}, // S (bits 15, 14, 13, 8, 6, 4, 0)
    {0x02,0x50}, // T (bits 9, 6, 4)
    {0x31,0x03}, // U (bits 13, 12, 8, 1, 0)
    {0x18,0x45}, // V (bits 12, 11, 6, 2, 0)
    {0x3C,0x03}, // W (bits 13, 12, 11, 10, 1, 0)
    {0x0C,0x4C}, // X (bits 11, 10, 6, 3, 2)
    {0xE1,0x43}, // Y (bits 15, 14, 13, 8, 6, 1, 0)
    {0x09,0x54}, // Z (bits 11, 8, 6, 4, 2)
    {0x04,0x04}, // [ (bits 10, 2)
    {0x04,0x48}, // \ (bits 10, 6, 3)
    {0x08,0x08}, // ] (bits 11, 3)
   
    //Special non-standard symbols
    {0xC0, 0x53}  // degree (bits 15, 14, 6, 4, 1, 0)
}; // DEL


#endif


VFDPanel_20S8D.h

Code: Select all

#ifndef VFD_20S8D_H
#define VFD_20S8D_H

#include "Settings.h"
#include "PT6311.h"
#include "Charset20S.h"

#define VFD_SEGMENTS          20
#define VFD_DIGITS          8
#define VFD_BYTES_PER_DIGIT       3
#define VFD_MAX_TEST_DELAY       100
#define VFD_FLASHING_DELAY       2
#define VFD_ROTOR_TEST_REVOLUTIONS    10
#define VFD_ROTOR_FRAMES       4
#define VFD_SCROLL_FRAMES       3
#define VFD_FLASH_NONE          0
#define VFD_FLASH_ALL          0xFF
#define VFD_FIRST_DISP_CHAR       0x20
#define VFD_FLASH_MODE_BIT       15
#define VFD_ACC_PIN_DEF       255
#define VFD_DEF_TONE          2960

class VFD_20S8D : public Print
{
    public:
        enum enum_TestState
        {   
            NOT_STARTED,   
            COLUMN_TEST,
            SEGMENT_TEST,
            DIMMING_TEST,
            GLOWING_TEST,
            CHARSET_TEST,
            CHARSET_TEST2,
            ROTOR_TEST,
            SLASH_EFFECT,
            SCROLL_EFFECT,
            PRODUCT_NAME,
            COMPLETED   
        };

        VFD_20S8D(uint8_t cs, uint8_t sclk, uint8_t data);

        void reset();
        void displayOnCmd(uint8_t dimming);
        void displayOffCmd();
        void setCur(uint8_t col);

        //Send ASCII value to display
        size_t write(uint8_t value);
        //Send ASCII value to intermediate buffer
        void write_f(uint8_t value, uint8_t dstIndex, uint8_t dispColumn);

        //Transfer array to display
        uint8_t write(uint8_t* buffer, uint8_t dstIndex, uint8_t len);
        //Transfer array to intermediate buffer
        uint8_t write_f(uint8_t* buffer, uint8_t dstIndex, uint8_t len);
        //Transfer string from program memory to intermediate buffer
        void print_f_p(const prog_char str[]);
        //Transfer whole intermediate buffer to display
        void flipFrame();
        void flipFlashState();
   void clearFrame();

        uint8_t getFlashAttr(uint8_t index);
        void setFlashAttr(uint8_t index, uint8_t value);

        uint8_t columnTest();
        uint8_t segmentTest();
        uint8_t dimmingTest();
        uint8_t glowingTest();
        uint8_t charsetTest();
        uint8_t charsetTest2();
        uint8_t rotorTest();
        inline void renderRotor(uint8_t addr, uint8_t idx);
        uint8_t dispProductName();

        uint8_t slashEffect();
        uint8_t scrollEffect();

        uint8_t testStep();

        void initScroll_p(const prog_char str[]);
        uint8_t scrollStep();

protected:
        uint8_t _rotorState, _rled, _gled, _bled, _lsnr, _standby, _powerdown;
        uint16_t _flashAttr,_testBt;
        enum_TestState _tstState;
        uint8_t _vfdFrame[VFD_BYTES_PER_DIGIT * VFD_DIGITS];
//        prog_char *scrollPntr;
        PT6311 driver;
        prog_char *_scrollPntr;
        uint8_t _scrollLeadingIdx;
};

#endif


VFDPanel_20S8D.cpp

Code: Select all

#include "VFDPanel_20S8D.h"

VFD_20S8D::VFD_20S8D(uint8_t cs, uint8_t sclk, uint8_t data)
{
    driver.init(cs, sclk, data);
}

void VFD_20S8D::reset()
{
    driver.reset(VFD_DISP_MODE_8D20S);

    driver.addrSetCmd(0);
    clearFrame();
    flipFrame();

    _testBt = 0;
    _tstState = NOT_STARTED;

    _flashAttr = 0;
}

void VFD_20S8D::displayOnCmd(uint8_t dimming)
{
    driver.displayOnCmd(dimming);
}

void VFD_20S8D::displayOffCmd()
{
    driver.displayOffCmd();
}

void VFD_20S8D::setCur(uint8_t col)
{
    if (col >= VFD_DIGITS) col = 0;
    driver.addrSetCmd(col * VFD_BYTES_PER_DIGIT);
}

size_t VFD_20S8D::write(uint8_t value)
{
    driver.displayMemWriteCmd(true, false);

    if (value < VFD_FIRST_DISP_CHAR) value = VFD_FIRST_DISP_CHAR;

    for (uint8_t i = 0; i < VFD_BYTES_PER_DIGIT; i++)
    {
        uint8_t chrset = pgm_read_byte(&FONT_PGM[(value - VFD_FIRST_DISP_CHAR)][i]);
        driver.data(chrset, false, ((i + 1) == VFD_BYTES_PER_DIGIT));
    }
    return 1;
}

void VFD_20S8D::write_f(uint8_t value, uint8_t dstIndex, uint8_t dispColumn)
{
    if (dstIndex > (VFD_DIGITS - 1) * VFD_BYTES_PER_DIGIT) return;

    if (value < VFD_FIRST_DISP_CHAR) value = VFD_FIRST_DISP_CHAR;

    for (uint8_t i = 0; i < (VFD_BYTES_PER_DIGIT); i++)
    {
        uint8_t chrset = pgm_read_byte(&FONT_PGM[(value - VFD_FIRST_DISP_CHAR)][i]);

        //Fixme later: if (dispColumn) chrset |= 1 << 5;
        if (i == 1 && dispColumn) chrset |= 1 << 5;

        _vfdFrame[dstIndex + i] = chrset;
    }
}

uint8_t VFD_20S8D::write(uint8_t* buffer, uint8_t dstIndex, uint8_t len)
{
    if (len == 0 || (dstIndex >= VFD_DIGITS * VFD_BYTES_PER_DIGIT)) return 0;
    if (len > VFD_DIGITS * VFD_BYTES_PER_DIGIT - dstIndex)
        len = VFD_DIGITS * VFD_BYTES_PER_DIGIT - dstIndex;

    driver.addrSetCmd(dstIndex);

    driver.displayMemWriteCmd(true, false);
    for (uint8_t i = 0; i < len-1; i++)
    {
         driver.data(buffer[i], false, false);
    }
    driver.data(buffer[len-1], false, true);

    return len;
}

uint8_t VFD_20S8D::write_f(uint8_t* buffer, uint8_t dstIndex, uint8_t len)
{
    if (len == 0 || (dstIndex >= VFD_DIGITS * VFD_BYTES_PER_DIGIT)) return 0;
    if (len > VFD_DIGITS * VFD_BYTES_PER_DIGIT - dstIndex)
        len = VFD_DIGITS * VFD_BYTES_PER_DIGIT - dstIndex;

    memcpy(&_vfdFrame[dstIndex], buffer, len);

    return len;
}

void VFD_20S8D::print_f_p(const prog_char str[])
{
    char c;
    uint8_t idx = 0;
    if(!str) return;

    clearFrame();
   
    while((c = pgm_read_byte(str++)))
    {
        write_f(c, idx, false);
        idx += VFD_BYTES_PER_DIGIT;
    }
}

uint8_t VFD_20S8D::testStep()
{
    switch (_tstState)
    {
        case NOT_STARTED:
            {
           _tstState = COLUMN_TEST;
                _testBt = 0;
            }
            break;

        case COLUMN_TEST:
            if (!columnTest())
            {
                _testBt = 0;
                _tstState = SEGMENT_TEST;
            }
            break;

        case SEGMENT_TEST:
            if (!segmentTest())
            {
                _tstState = DIMMING_TEST;
                _testBt = VFD_DIMMING_MAX;
            }
            break;

        case DIMMING_TEST:
            if (!dimmingTest())
            {
                _tstState = GLOWING_TEST;
                _testBt = 0;
            }
            break;

        case GLOWING_TEST:
            if (!glowingTest())
            {
                _tstState = CHARSET_TEST;
                _testBt = (VFD_MAX_TEST_DELAY / 4);
            }
            break;

        case CHARSET_TEST:
            if (!charsetTest())
            {
                _tstState = CHARSET_TEST2;
                _testBt = VFD_MAX_TEST_DELAY / 2;
            }
            break;

        case CHARSET_TEST2:
            if (!charsetTest2())
            {
               _tstState = ROTOR_TEST;
               _rotorState = 0;
               _testBt = VFD_ROTOR_FRAMES * VFD_ROTOR_TEST_REVOLUTIONS;
            }
            break;

        case ROTOR_TEST:
            if (!rotorTest())
            {
                _tstState = SCROLL_EFFECT;
                _testBt = (VFD_MAX_TEST_DELAY / 2);
                _rotorState = 0;
            }
            break;

        case SCROLL_EFFECT:
            //if (!scrollEffect())
            {
                //_tstState = COMPLETED;
                _tstState = PRODUCT_NAME;
                _testBt = (VFD_MAX_TEST_DELAY / 4);
            }
            break;

        case SLASH_EFFECT:
            if (!slashEffect())
                _tstState = COMPLETED;
            break;
 
        case PRODUCT_NAME:
            if (!dispProductName())
                _tstState = COMPLETED;
            break;

        case COMPLETED:
            _tstState = NOT_STARTED;
            break;
        default:
            _tstState = NOT_STARTED;
    }
    return _tstState;
}

uint8_t VFD_20S8D::columnTest()
{
    if (_testBt < VFD_DIGITS)
    {
        if (_testBt == 0)
        {
            driver.addrSetCmd(0);
            for (uint8_t i = 0; i < VFD_DIGITS; i++)
            {
                driver.displayMemWriteCmd(true, false);
                for (uint8_t j = 0; j < VFD_BYTES_PER_DIGIT; j++)
                {
                    if (i == 0)
                    {
                        driver.data(0xFF, false, ((j + 1) == VFD_BYTES_PER_DIGIT));
                    }else{
                        driver.data(0, false, ((j + 1) == VFD_BYTES_PER_DIGIT));
                    }
                }
            }
        }else{
            driver.addrSetCmd((_testBt - 1) * VFD_BYTES_PER_DIGIT);
            driver.displayMemWriteCmd(true, false);
            for (uint8_t j = 0; j < (VFD_BYTES_PER_DIGIT); j++)
                driver.data(0, false, false);
            for (uint8_t j = 0; j < (VFD_BYTES_PER_DIGIT); j++)
                driver.data(0xFF, false, ((j + 1) == VFD_BYTES_PER_DIGIT));
        }
        _testBt++;
        return true;
    }else return false;
}

uint8_t VFD_20S8D::segmentTest()
{
    if (_testBt < VFD_SEGMENTS)
    {
        driver.addrSetCmd(0);
        for (uint8_t i = 0; i < VFD_DIGITS; i++)
        {
            driver.displayMemWriteCmd(true, false);
            driver.data((1 << _testBt ) & 0xFF, false, false);
            driver.data(((1 << _testBt ) >> 8) & 0xFF, false, false);
            driver.data(((1 << _testBt ) >> 16) & 0xFF, false, true);
        }
        _testBt++;
        return true;
    }else return false;
}

uint8_t VFD_20S8D::dimmingTest()
{
    if (_testBt == VFD_DIMMING_MAX)
    {
        driver.addrSetCmd(0);
        for (uint8_t i = 0; i < VFD_DIGITS; i++)
        {
            driver.displayMemWriteCmd(true, false);
            for (uint8_t j = 0; j < VFD_BYTES_PER_DIGIT; j++)
                driver.data(0xFF, false, ((j + 1) == VFD_BYTES_PER_DIGIT));
        }

        displayOnCmd(_testBt);
        _testBt--;
        return true;
    }else
    {
        displayOnCmd(_testBt);
        if (_testBt != 0)
        {
            _testBt--;
            return true;
        }
    }
    return false;
}

uint8_t VFD_20S8D::glowingTest()
{
    if (_testBt == 0)
    {
        driver.addrSetCmd(0);
        for (uint8_t i = 0; i < VFD_DIGITS; i++)
        {
            driver.displayMemWriteCmd(true, false);
            for (uint8_t j = 0; j < VFD_BYTES_PER_DIGIT; j++)
                driver.data(0xFF, false, ((j + 1) == VFD_BYTES_PER_DIGIT));
            driver.data(0xFF, false, false);
            driver.data(0xFF, false, true);
        }

        displayOnCmd(_testBt);
        _testBt++;
        return true;
    }else
    {
        displayOnCmd(_testBt);
        if (_testBt < VFD_DIMMING_MAX)
        {
            _testBt++;
            return true;
        }
    }
    return false;
}


uint8_t VFD_20S8D::charsetTest2()
{
    if (_testBt != 0)
    {
        if (_testBt == (VFD_MAX_TEST_DELAY / 2))
        {
            //Sending characters one by one

            //addrSetCmd(0);
            //for (uint8_t testChar = 0x30; testChar < (0x30 + VFD_DIGITS); testChar++)
            //    write(testChar);
   
            //Sending characters to intermediate buffer and
            //then send video data in one go
            //for (uint8_t testChar = 0x57; testChar < (0x57 + VFD_DIGITS); testChar++)
            //    write_f(testChar, ( testChar - 0x57 ) * VFD_BYTES_PER_DIGIT, false);
            driver.addrSetCmd(0);
            print_f_p(PSTR("()*+-./\\"));
           
            _flashAttr = 0;
            flipFrame();

            setFlashAttr(VFD_DIGITS + 1, (1 << (VFD_DIGITS - 1)));
        }else
        {
            //Using flashing attributes
            if (_testBt % VFD_FLASHING_DELAY == 0)
            {
                flipFlashState();
                flipFrame();
            }
            if ((_testBt % (VFD_FLASHING_DELAY * 4)) == 0)
            {
                uint8_t flashVal = (getFlashAttr(VFD_DIGITS + 1) >> 1);
                if (flashVal == 0) flashVal = (1 << (VFD_DIGITS - 1));
                setFlashAttr(VFD_DIGITS + 1, flashVal);
            }
        }
        _testBt--;
        return true;
    }
    return false;
}

uint8_t VFD_20S8D::charsetTest()
{
    if (_testBt != 0)
    {
        if (_testBt == VFD_MAX_TEST_DELAY / 4)
        {
            driver.addrSetCmd(0);
            for (uint8_t testChar = 0x30; testChar < 0x30 + VFD_DIGITS; testChar++)
                write(testChar);
        }else if (_testBt == VFD_MAX_TEST_DELAY * 3 / 16)
        {
            driver.addrSetCmd(0);
            print(F("ABCDEFGH"));
        }else if (_testBt == VFD_MAX_TEST_DELAY / 8)
        {
            driver.addrSetCmd(0);
            print(F("IJKLMNOP"));
        }else if (_testBt == VFD_MAX_TEST_DELAY / 16)
        {
            driver.addrSetCmd(0);
            print(F("QRSTUVWX"));
        }
        _testBt--;
        return true;
    }
    return false;
}

uint8_t VFD_20S8D::dispProductName()
{
    if (_testBt != 0)
    {
        if (_testBt == VFD_MAX_TEST_DELAY * 5 / 20)
        {
            driver.addrSetCmd(0);
            print(F(" MAGIC  "));
        }else if (_testBt == VFD_MAX_TEST_DELAY * 4 / 20)
        {
            driver.addrSetCmd(0);
            print(F("  VFD   "));           
        }else if (_testBt == VFD_MAX_TEST_DELAY * 3 / 20)
        {
            driver.addrSetCmd(0);
            print(F(" PANEL  "));
        }else if (_testBt == VFD_MAX_TEST_DELAY * 2 / 20)
        {
            driver.addrSetCmd(0);
            print(F("16 SEGMN"));
        }else if (_testBt == VFD_MAX_TEST_DELAY * 1 / 20)
        {
            driver.addrSetCmd(0);
            print(F("8 DIGITS"));
        }
        _testBt--;
        return true;
    }
    return false;
}

inline void VFD_20S8D::renderRotor(uint8_t addr, uint8_t idx)
{
    driver.addrSetCmd(addr);
    driver.displayMemWriteCmd(true, false);
    uint8_t chrset = pgm_read_byte(&ROTOR_PGM[idx][0]);
    driver.data(chrset, false, false);
    chrset = pgm_read_byte(&ROTOR_PGM[idx][1]);
    driver.data(chrset, false, true);
}

uint8_t VFD_20S8D::rotorTest()
{
    if (_testBt!= 0)
    {
        if (_testBt == VFD_ROTOR_FRAMES * VFD_ROTOR_TEST_REVOLUTIONS)
        {
            driver.addrSetCmd(0);
            for (uint8_t i = 0; i < VFD_DIGITS; i++)
            {
                driver.displayMemWriteCmd(true, false);
                driver.data(0, false, false);
                driver.data(0, false, false);
                driver.data(0, false, true);
            }
        }

        renderRotor(0, (_rotorState & 0xF));

        uint8_t bckRotSt = VFD_ROTOR_FRAMES - ((_rotorState >> 4) & 0xF);
        if (bckRotSt == VFD_ROTOR_FRAMES) bckRotSt = 0;
        renderRotor(2 * VFD_BYTES_PER_DIGIT, bckRotSt);

        renderRotor(5 * VFD_BYTES_PER_DIGIT, ((_rotorState >> 4) & 0xF));

        bckRotSt = VFD_ROTOR_FRAMES - (_rotorState & 0xF);
        if (bckRotSt == VFD_ROTOR_FRAMES) bckRotSt = 0;
        renderRotor((VFD_DIGITS - 1) * VFD_BYTES_PER_DIGIT, bckRotSt);

        _rotorState = (_rotorState & 0xF0) | ((_rotorState & 0xF) + 1);
        if ((_rotorState & 0xF) >= VFD_ROTOR_FRAMES) _rotorState &= 0xF0;

        if (_testBt % 2 == 0)
        {
            _rotorState = ((_rotorState + 0x10) & 0xF0) | (_rotorState & 0xF);
            if ((( _rotorState >> 4 ) & 0xF) >= VFD_ROTOR_FRAMES) _rotorState &= 0xF;
        }

        _testBt--;
        return true;
    }   
    return false;
}

void VFD_20S8D::flipFrame()
{
    if (_flashAttr == 0 || ((_flashAttr >> VFD_FLASH_MODE_BIT ) & 0x1) == 0)
    {
        write((uint8_t*)&_vfdFrame, 0, VFD_BYTES_PER_DIGIT * VFD_DIGITS);
        return;
    }

    for (uint8_t i = 0; i < VFD_DIGITS; i++)
    {
        if ((( _flashAttr >> (VFD_DIGITS - i - 1) ) & 0x1) == 0)
        {
            //Send bytes representing single digit to VFD
            write(&_vfdFrame[i * VFD_BYTES_PER_DIGIT], i * VFD_BYTES_PER_DIGIT,
                VFD_BYTES_PER_DIGIT);
        }else{
            //The digit is not visible during this period in time
            driver.addrSetCmd(i * VFD_BYTES_PER_DIGIT);
            //Display space char
            write(0x20);   
        }
    }
}

void VFD_20S8D::clearFrame()
{
    memset(&_vfdFrame, 0, sizeof(_vfdFrame));
}

uint8_t VFD_20S8D::getFlashAttr(uint8_t index)
{
    if (index >= VFD_DIGITS) return (_flashAttr & ~(1 << VFD_FLASH_MODE_BIT));
    else return (( _flashAttr >> index ) & 0x1);
}
     
void VFD_20S8D::setFlashAttr(uint8_t index, uint8_t value)
{
    if (index >= VFD_DIGITS)
        _flashAttr = (_flashAttr & (1 << VFD_FLASH_MODE_BIT)) | (value & ~(1 << VFD_FLASH_MODE_BIT));
    else _flashAttr |= 1 << index;
}

void VFD_20S8D::flipFlashState()
{
    if (((_flashAttr >> VFD_FLASH_MODE_BIT ) & 0x1) == 0)
    {
        _flashAttr |= 1 << VFD_FLASH_MODE_BIT;
    }else{
        _flashAttr &= ~(1 << VFD_FLASH_MODE_BIT);
    }
}

uint8_t VFD_20S8D::slashEffect()
{
    if (_testBt != 0)
    {
        if (_testBt == VFD_DIGITS)
        {
            memset(&_vfdFrame, 0, sizeof(_vfdFrame));
            write_f(0x2F, 0, false);
            write_f(0x5C, (VFD_DIGITS - 1) * VFD_BYTES_PER_DIGIT, false );
        }else{
            //Move everything to the center
            uint16_t* vfdPntr = (uint16_t*)&_vfdFrame;
            uint16_t leftVal, rightVal;
            for (uint8_t i = ((VFD_DIGITS - 1) / 2 + 1); i < VFD_DIGITS; i++)
            {
                leftVal = vfdPntr[VFD_DIGITS - 1 - i];
                rightVal = vfdPntr[i];
               
                vfdPntr[i - 1] |= rightVal;
                vfdPntr[VFD_DIGITS - i] |= leftVal;
            }
            write_f(0x2F, 0, false);
            write_f(0x5C, (VFD_DIGITS - 1) * VFD_BYTES_PER_DIGIT, false);
        }

        flipFrame();

        _testBt--;
        return true;
    }   
    return false;
}

uint8_t VFD_20S8D::scrollEffect()
{
    if (_testBt != 0)
    {
        for (uint8_t i = 0; i < sizeof(_vfdFrame); i++)
            _vfdFrame[i] = pgm_read_byte(&SCROL_FRAMES[_rotorState][i]);

        _flashAttr = 0; 
        flipFrame();

        _rotorState++;
        if (_rotorState >= VFD_SCROLL_FRAMES) _rotorState = 0;

        _testBt--;
        return true;   
    }
    return false;
}

void VFD_20S8D::initScroll_p(const prog_char str[])
{
    _scrollPntr = (prog_char*)str;
}

uint8_t VFD_20S8D::scrollStep( void )
{
    char c;
    uint8_t idx = 0;
    uint8_t digitsLeft = VFD_DIGITS;
    if(!_scrollPntr) return false;

    prog_char* str = _scrollPntr;

    clearFrame();

    //Filling in blank spaces first so that scrolling
    //starts from the very right
    for(uint8_t i = 0; i < _scrollLeadingIdx; i++)
    {
        write_f(0x20, idx, false);
        idx += VFD_BYTES_PER_DIGIT;
        digitsLeft--;
    }
   
    while((digitsLeft > 0) && (c = pgm_read_byte(str++)))
    {
        write_f(c, idx, false);
        idx += VFD_BYTES_PER_DIGIT;
        digitsLeft--;
    }

    flipFrame();

    if (_scrollLeadingIdx > 0)
    {
        _scrollLeadingIdx--;
        return true;
    }
    else _scrollPntr++;

    if (!pgm_read_byte(_scrollPntr)) return false;
    else return true;
}


Now I will "draw" charset20S.h for each character.

Can we go now for the next step? Symbols or Points?

Many thanks!

Rafael
Posts: 12
Joined: Tue Mar 25, 2014 4:23 pm

Re: Driving VFD panels with PT6311 controller

Postby Rafael » Fri Apr 22, 2016 10:45 pm

Hi,

While I was drawing the characters, I noticed that there is an extra byte (3) being sent in some digits.

Image

Do you have any idea where is this extra byte is come from?

Charset_20S.h

Code: Select all

{0x01,0x00}, // 1


3rd byte in most case is for symbols, charset map is sending two bytes and this VFD needs 2 bytes + 1 per digit, but in some cases, need to add extra bits on second by, please look:

Code: Select all

  fill_mem(0b00000000, 1, 0);
  fill_mem(0b00000000, 1, 1); 
  fill_mem(0b00000010, 1, 2);  // 0b00000010 "POWER"   
 
  fill_mem(0b00000000, 1, 3);
  fill_mem(0b00000000, 1, 4); 
  fill_mem(0b00000010, 1, 5);  // 0b00000010 "STOP"
 
  fill_mem(0b00000000, 1, 6);
  fill_mem(0b00000000, 1, 7); 
  fill_mem(0b00000010, 1, 8);  // 0b00000010 "REC"
 
  fill_mem(0b00000000, 1, 9);
  fill_mem(0b00000000, 1, 10); 
  fill_mem(0b00000011, 1, 11); // 0b00000001 ":" and 00000010 "PLAY"
 
  fill_mem(0b00000000, 1, 12);
  fill_mem(0b00000000, 1, 13); 
  fill_mem(0b00000110, 1, 14); // 0b00000010 "PAUSE" and 0b00000100 "CLOCK"
 
  fill_mem(0b00000000, 1, 15);
  fill_mem(0b00000000, 1, 16); 
  fill_mem(0b00000101, 1, 17); // 0b00000001 ":" e  0b00000100 "$"
 
  fill_mem(0b00000000, 1, 18);
  fill_mem(0b00000000, 1, 19); 
  fill_mem(0b00000010, 1, 20); // 0b00000010 "DOLBY"

  fill_mem(0b00000000, 1, 21);
  fill_mem(0b10000000, 1, 22); // 0b10000000 "USB"
  fill_mem(0b00001111, 1, 23); // 0b00000001 "TXT" and 0b00000010 "HD" and 0b00000100 "EPG" and 0b00001000 "SUB"


Thanks.

Rafael
Posts: 12
Joined: Tue Mar 25, 2014 4:23 pm

Re: Driving VFD panels with PT6311 controller

Postby Rafael » Sat Apr 23, 2016 2:07 am

Not too smart but, works...

Code: Select all

void VFD_20S8D::simbolos(uint8_t index)
{
    switch (index)
    {
   case 0:   // Power
      _vfdFrame[2] = 0x02;
      break;
   case 1:   // Stop
      _vfdFrame[5] = 0x02;
      break;
   case 2:   // Rec
      _vfdFrame[8] = 0x02;
      break;
    }
}

User avatar
dmitryp
Site Admin
Posts: 45
Joined: Sun Aug 04, 2013 1:16 am
Location: Sydney, Australia
Contact:

Re: Driving VFD panels with PT6311 controller

Postby dmitryp » Mon May 02, 2016 12:21 am

Hi Rafael,

Rafael wrote:Hi,

While I was drawing the characters, I noticed that there is an extra byte (3) being sent in some digits.

Do you have any idea where is this extra byte is come from?



There shouldn't be an extra (third) byte. Something is not quite right. Could you provide the sketch which exhibits this issue?

Thanks,
Dmitry

Rafael
Posts: 12
Joined: Tue Mar 25, 2014 4:23 pm

Re: Driving VFD panels with PT6311 controller

Postby Rafael » Mon May 02, 2016 5:26 pm

Hi...

Just this:

Code: Select all

#include <util/delay.h>
#include <VFDPanel_20S8D.h>

#define VFD_CS_PIN 2   //Just an example, specify your own correct pin number! This is STB in PT6311 datasheet notation.
#define VFD_CLK_PIN 3  //Just an example, specify your own correct pin number! This is CLK in PT6311 datasheet notation.
#define VFD_DATA_PIN 4 //Just an example, specify your own correct pin number! This is DIN in PT6311 datasheet notation.

VFD_20S8D vfd(VFD_CS_PIN, VFD_CLK_PIN, VFD_DATA_PIN);

void setup()
{
  vfd.reset();
  vfd.clearFrame();
  vfd.print_f_p(PSTR("0"));
  vfd.flipFrame(); 
}

void loop()

}


I was drawing char by char...

Code: Select all

  vfd.print_f_p(PSTR("1"));
    vfd.print_f_p(PSTR("2"));
    ...
 


For digit, there are two bytes and for symbols, third byte.

If I set:

Code: Select all

#define VFD_BYTES_PER_DIGIT       2


Will damage this:

Code: Select all

uint8_t _vfdFrame[VFD_BYTES_PER_DIGIT * VFD_DIGITS];


Thanks.


Return to “General Technical Discussions”

Who is online

Users browsing this forum: No registered users and 1 guest