16 segment display library for mbed This routine support 4, 6 and 8 digit anode-common or cathode-common LED.

Dependents:   16segmentLED_test

Stnseg.cpp

Committer:
morecat_lab
Date:
2015-02-08
Revision:
0:420d710da1c5

File content as of revision 0:420d710da1c5:

/*
  Stnseg.cpp - mbed library for 4/6/8 digit Sixteen (16) segment LED driver.
  Copyright 2015 by morecat_lab
  
  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
*/

#include "Stnseg.h"
#include <Timer.h>

const uint16_t Stnseg::numConv[] = {
    NUM_PAT16_0, NUM_PAT16_1, NUM_PAT16_2, NUM_PAT16_3,
    NUM_PAT16_4, NUM_PAT16_5, NUM_PAT16_6, NUM_PAT16_7,
    NUM_PAT16_8, NUM_PAT16_9, NUM_PAT16_A, NUM_PAT16_B,
    NUM_PAT16_C, NUM_PAT16_D, NUM_PAT16_E, NUM_PAT16_F};


// 4 digit
Stnseg::Stnseg(PinName data,PinName clock, PinName latch,PinName dp,
           PinName d1,PinName d2, PinName d3, PinName d4) :
           _dataPin(data), _clockPin(clock), _latchPin(latch), _dpPin(dp), 
           _digPins(d1, d2, d3, d4)
{
    _numOfDigs = 4;
    _updateInterval = (8333 / 4);
    _zeroSupress = true;
    _kcommon = false;
}

// 6 digit
Stnseg::Stnseg(PinName data,PinName clock, PinName latch,PinName dp,
           PinName d1,PinName d2, PinName d3, PinName d4,
           PinName d5,PinName d6) :
           _dataPin(data), _clockPin(clock), _latchPin(latch), _dpPin(dp), 
           _digPins(d1, d2, d3, d4, d5, d6)
{
    _numOfDigs = 6;
    _updateInterval = (8333 / 6);
    _zeroSupress = true;
    _kcommon = false;
}

// 8 digit
Stnseg::Stnseg(PinName data,PinName clock, PinName latch,PinName dp,
           PinName d1,PinName d2, PinName d3, PinName d4,
           PinName d5,PinName d6, PinName d7, PinName d8) :
           _dataPin(data), _clockPin(clock), _latchPin(latch), _dpPin(dp), 
           _digPins(d1, d2, d3, d4, d5, d6, d7, d8)
{
    _numOfDigs = 8;
    _updateInterval = (8333 / 8);
    _zeroSupress = true;
    _kcommon = false;
}


void Stnseg::begin(void) {
    timer.start();
    clear();
}

void Stnseg::setAcommon(void) {
    _kcommon = false;
}

void Stnseg::setKcommon(void) {
    _kcommon = true;
}

uint16_t Stnseg::segCh(char i) {
    return numConv[i];
}

void Stnseg::setDot(int d) {
    _buffer[d] |= 0x010000;
}

void Stnseg::clearDot(int d) {
    _buffer[d] &= 0xfffe0000;
}

void Stnseg::writeNum(int n) {
    if (_numOfDigs == 4) {
        writeNum4(n);
    } else if (_numOfDigs == 6) {
        writeNum6(n);
    } else if (_numOfDigs == 8) {
        writeNum8((long)n);
    }
}


void Stnseg::writeNum4(int n) {
    if (n < 10000) {
        _buffer[0] = segCh((n % 10000) / 1000);
        _buffer[1] = segCh((n % 1000) / 100);
        _buffer[2] = segCh((n % 100) / 10);
        _buffer[3] = segCh(n % 10);
        supressZero();
    } else {
        _buffer[0] = _buffer[1] = _buffer[2] = _buffer[3] = NUM_PAT16_MINUS;// overflow
    }
}

void Stnseg::writeNum6(int n) {
    if (n < 10000) {
        _buffer[0] = segCh((n % 1000000) / 100000);
        _buffer[1] = segCh((n % 100000) / 10000);
        _buffer[2] = segCh((n % 10000) / 1000);
        _buffer[3] = segCh((n % 1000) / 100);
        _buffer[4] = segCh((n % 100) / 10);
        _buffer[5] = segCh(n % 10);
        supressZero();
    } else {
        _buffer[0] = _buffer[1] = _buffer[2] = _buffer[3] = NUM_PAT16_MINUS;// overflow
    }
}

void Stnseg::writeNum8(int n) {
    if (n < 1000000) {
        _buffer[0] = segCh((n % 100000000) / 10000000);
        _buffer[1] = segCh((n % 10000000) / 1000000);
        _buffer[2] = segCh((n % 1000000) / 100000);
        _buffer[3] = segCh((n % 100000) / 10000);
        _buffer[4] = segCh((n % 10000) / 1000);
        _buffer[5] = segCh((n % 1000) / 100);
        _buffer[6] = segCh((n % 100) / 10);
        _buffer[7] = segCh(n % 10);
        supressZero();
    } else {
        _buffer[0] = _buffer[1] = _buffer[2] = _buffer[3] = _buffer[4] = _buffer[5] = NUM_PAT16_MINUS;// overflow
    }
}

void Stnseg::writeNum(char d1, char d2) {
    _buffer[0] = segCh(d1);
    _buffer[1] = segCh(d2);
    supressZero();
}

void Stnseg::writeNum(char d1, char d2, char d3, char d4) {
    _buffer[0] = segCh(d1);
    _buffer[1] = segCh(d2);
    _buffer[2] = segCh(d3);
    _buffer[3] = segCh(d4);
    supressZero();
}

void Stnseg::writeNum(char d1, char d2, char d3, char d4,
                    char d5, char d6, char d7, char d8)
{
    _buffer[0] = segCh(d1);
    _buffer[1] = segCh(d2);
    _buffer[2] = segCh(d3);
    _buffer[3] = segCh(d4);
    _buffer[4] = segCh(d5);
    _buffer[5] = segCh(d6);
    _buffer[6] = segCh(d7);
    _buffer[7] = segCh(d8);
    supressZero();
}

void Stnseg::writeHex(long n) {
    if (_numOfDigs == 4) {
        _buffer[0] = segCh((n >> 12) & 0xf);
        _buffer[1] = segCh((n >> 8) & 0xf);
        _buffer[2] = segCh((n >> 4) & 0xf);
        _buffer[3] = segCh(n & 0xf);
    } else if (_numOfDigs == 6) {
        _buffer[0] = segCh((n >> 20) & 0xf);
        _buffer[1] = segCh((n >> 16) & 0xf);
        _buffer[2] = segCh((n >> 12) & 0xf);
        _buffer[3] = segCh((n >> 8) & 0xf);
        _buffer[4] = segCh((n >> 4) & 0xf);
        _buffer[5] = segCh(n & 0xf);
    } else if (_numOfDigs == 8) {
        _buffer[0] = segCh((n >> 28) & 0xf);
        _buffer[1] = segCh((n >> 24) & 0xf);
        _buffer[2] = segCh((n >> 20) & 0xf);
        _buffer[3] = segCh((n >> 16) & 0xf);
        _buffer[4] = segCh((n >> 12) & 0xf);
        _buffer[5] = segCh((n >> 8) & 0xf);
        _buffer[6] = segCh((n >> 4) & 0xf);
        _buffer[7] = segCh(n & 0xf);
    }
    supressZero();
}

void Stnseg::setZeroSupress(bool t) {
    _zeroSupress = t;
}

void Stnseg::supressZero() {
    int i;
    if (_zeroSupress ) {
        for (i = 0 ; i < (_numOfDigs-1) ; i++) {
            if (_buffer[i] == segCh(0)) {
                _buffer[i] = _buffer[i] & 0x1000;
            } else {
                break;
            }
        }
    }
}

void Stnseg::writeRawData(uint32_t d1, uint32_t d2, uint32_t d3, uint32_t d4) {
    _buffer[0] = d1;
    _buffer[1] = d2;
    _buffer[2] = d3;
    _buffer[3] = d4;
}

void Stnseg::writeRawData(uint32_t d1, uint32_t d2, uint32_t d3, uint32_t d4,
                          uint32_t d5, uint32_t d6) {
    _buffer[0] = d1;
    _buffer[1] = d2;
    _buffer[2] = d3;
    _buffer[3] = d4;
    _buffer[4] = d5;
    _buffer[5] = d6;
}
void Stnseg::writeRawData(uint32_t d1, uint32_t d2, uint32_t d3, uint32_t d4,
                          uint32_t d5, uint32_t d6, uint32_t d7, uint32_t d8) {
    _buffer[0] = d1;
    _buffer[1] = d2;
    _buffer[2] = d3;
    _buffer[3] = d4;
    _buffer[4] = d5;
    _buffer[5] = d6;
    _buffer[6] = d7;
    _buffer[7] = d8;
}

void Stnseg::write(uint8_t d, uint32_t value) {
    _buffer[d] = value;
}

void Stnseg::clear(void) {
    int i;
    for(i=0;i<8;i++){
        _buffer[i] = 0;
    }
    _dig = _numOfDigs - 1;
    _digPins = ( _kcommon) ? 0xff : 0;
}

void Stnseg::turnOff(void) {
    if ( _kcommon) {
        _digPins = 0xff;   // set HIGH
    } else {
        _digPins = 0;  // set LOW
    }
}

void Stnseg::turnOn(void) {
    if ( _kcommon) {
        _digPins = ~(1 << _dig); // set LOW
    } else {
        _digPins = (1 << _dig); // set HIGH
     }
}

void Stnseg::updateSeg(void) {
    if( (++_dig) >= _numOfDigs)
        _dig = 0;
    _latchPin = 0;
    for (int col = 0 ; col < 16 ; col++) {  // forward order
        _clockPin = 0;
        if(_buffer[_dig] & (1 << col)){
            _dataPin = 1;
        } else {
            _dataPin = 0;
        }
        _clockPin = 1;
    }
    _latchPin = 1;
    if ((_buffer[_dig] & 0x10000) != 0) {
        _dpPin = 1;
    } else {
        _dpPin = 0;
    }
}

void Stnseg::updateWithDelay(int ms) {
    timer.reset();  // to avoid overflow 32bit counter  (~=30min)
    int start = timer.read_ms();
    _dig = _numOfDigs - 1;
    turnOff();
    do {
        for (int i = 0 ; i < _numOfDigs ; i++) {
            updateSeg();
            turnOn();
            wait(0.001f); // wait 1ms
            turnOff();
        }
        if ((timer.read_ms() - start) >= ms) {
            break;
        }
    } while(1);
}

void Stnseg::updateOnce(void) {
    uint8_t i;
    _dig = _numOfDigs - 1;
    turnOff();
    for (i = 0 ; i < _numOfDigs ; i++) {
        updateSeg();
        turnOn();
        wait(0.001f); // wait 1ms
        turnOff();
    }
}

// EOF