7 segment display library for mbed This routine support 2,4 and 8 digit anode-common or cathode-common LED.
Sseg.cpp
- Committer:
- morecat_lab
- Date:
- 2015-07-05
- Revision:
- 12:59ac7a4f3d9c
- Parent:
- 11:8be75770e375
File content as of revision 12:59ac7a4f3d9c:
/*
Sseg.cpp - mbed library for 2/4/8 digit seven segment LED driver.
Copyright 2013,2014,2015 by morecat_lab
base on Dots library.
Copyright 2010 arms22. All right reserved.
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 "Sseg.h"
#include <Timer.h>
const int Sseg::numConv[] = {
NUM_PAT_0, NUM_PAT_1, NUM_PAT_2, NUM_PAT_3,
NUM_PAT_4, NUM_PAT_5, NUM_PAT_6, NUM_PAT_7,
NUM_PAT_8, NUM_PAT_9, NUM_PAT_A, NUM_PAT_B,
NUM_PAT_C, NUM_PAT_D, NUM_PAT_E, NUM_PAT_F};
// 2 digit
Sseg::Sseg(PinName a,PinName b,PinName c,PinName d,
PinName e,PinName f,PinName g,PinName dp,
PinName d1,PinName d2)
{
_numOfDigs = 2;
PinName segPins[8] = {a, b, c, d, e, f, g, dp};
PinName digPins[2] = {d1, d2};
for (int i=0; i<8; i++) {
_segPins[i] = new DigitalOut(segPins[i]);
}
for (int i=0; i<_numOfDigs; i++) {
_digPins[i] = new DigitalOut(digPins[i]);
}
_updateInterval = (8333 / 2);
_zeroSupress = true;
_kcommon = false;
_sinkDriver = false;
}
// 4 digit
Sseg::Sseg(PinName a,PinName b,PinName c,PinName d,
PinName e,PinName f,PinName g,PinName dp,
PinName d1,PinName d2,PinName d3,PinName d4)
{
_numOfDigs = 4;
PinName segPins[8] = {a, b, c, d, e, f, g, dp};
PinName digPins[4] = {d1, d2, d3, d4};
for (int i=0; i<8; i++) {
_segPins[i] = new DigitalOut(segPins[i]);
}
for (int i=0; i<_numOfDigs; i++) {
_digPins[i] = new DigitalOut(digPins[i]);
}
_updateInterval = (8333 / 4);
_zeroSupress = true;
_kcommon = false;
_sinkDriver = false;
}
// 8 digit
Sseg::Sseg(PinName a,PinName b,PinName c,PinName d,
PinName e,PinName f,PinName g,PinName dp,
PinName d1,PinName d2,PinName d3,PinName d4,
PinName d5,PinName d6,PinName d7,PinName d8)
{
_numOfDigs = 8;
PinName segPins[8] = {a, b, c, d, e, f, g, dp};
PinName digPins[8] = {d1, d2, d3, d4, d5, d6, d7, d8};
for (int i=0; i<8; i++) {
_segPins[i] = new DigitalOut(segPins[i]);
}
for (int i=0; i<_numOfDigs; i++) {
_digPins[i] = new DigitalOut(digPins[i]);
} _updateInterval = (8333 / 8);
_zeroSupress = true;
_kcommon = false;
_sinkDriver = false;
}
void Sseg::begin(void) {
timer.start();
clear();
}
void Sseg::setAcommon(void) {
_kcommon = false;
}
void Sseg::setKcommon(void) {
_kcommon = true;
}
void Sseg::setSinkDriver(void) {
_sinkDriver = true;
}
char Sseg::segCh(char i) {
return Sseg::numConv[i];
}
void Sseg::setDot(int d) {
_buffer[d] |= 0x01;
}
void Sseg::clearDot(int d) {
_buffer[d] &= 0xfe;
}
void Sseg::writeNum(int n) {
if (_numOfDigs == 2) {
writeNum2(n);
} else if (_numOfDigs == 4) {
writeNum4(n);
} else if (_numOfDigs == 8) {
writeNum8((long)n);
}
}
void Sseg::writeNum2(int n) {
if (n < 100) {
_buffer[0] = segCh((n % 100) / 10);
_buffer[1] = segCh(n % 10);
Sseg::supressZero();
} else {
_buffer[0] = _buffer[1] = 0x02;// overflow
}
}
void Sseg::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);
Sseg::supressZero();
} else {
_buffer[0] = _buffer[1] = _buffer[2] = _buffer[3] = 0x02;// overflow
}
}
void Sseg::writeNum8(int n) {
_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);
Sseg::supressZero();
}
void Sseg::writeNum(char d1, char d2) {
_buffer[0] = segCh(d1);
_buffer[1] = segCh(d2);
Sseg::supressZero();
}
void Sseg::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);
Sseg::supressZero();
}
void Sseg::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);
Sseg::supressZero();
}
void Sseg::writeHex(int n) {
if(_numOfDigs == 2) {
_buffer[0] = segCh((n >> 4) & 0xf);
_buffer[1] = segCh(n & 0xf);
} else 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);
}
Sseg::supressZero();
}
void Sseg::writeHex(long n) {
_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);
Sseg::supressZero();
}
void Sseg::setZeroSupress(bool t) {
_zeroSupress = t;
}
void Sseg::supressZero() {
int i;
if (_zeroSupress ) {
for (i = 0 ; i < (_numOfDigs-1) ; i++) {
if (_buffer[i] == segCh(0)) {
_buffer[i] = _buffer[i] & 0x1;
} else {
break;
}
}
}
}
void Sseg::writeRawData(char d1, char d2) {
_buffer[0] = d1;
_buffer[1] = d2;
}
void Sseg::writeRawData(char d1, char d2, char d3, char d4) {
_buffer[0] = d1;
_buffer[1] = d2;
_buffer[2] = d3;
_buffer[3] = d4;
}
void Sseg::writeRawData(char d1, char d2, char d3, char d4,
char d5, char d6, char d7, char 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 Sseg::write(uint8_t x, uint8_t y, uint8_t value) {
uint8_t tmp,msk;
tmp = _buffer[y];
msk = 0x80 >> x;
tmp = tmp & ~msk;
tmp = tmp | (value ? msk : 0);
_buffer[y] = tmp;
}
void Sseg::write(uint8_t d, uint8_t value) {
_buffer[d] = value;
}
void Sseg::write(uint8_t y, const uint8_t values[], uint8_t size) {
uint8_t i;
for(i=0;i<size;i++)
_buffer[(y++) & 0x07] = values[i];
}
void Sseg::clear(void) {
int i;
for(i=0;i<8;i++){
_buffer[i] = 0;
}
_dig = _numOfDigs - 1;
}
void Sseg::turnOff(void) {
_digPins[_dig] -> write((_kcommon) ? 1 : 0);
}
void Sseg::turnOn(void) {
_digPins[_dig] -> write((_kcommon) ? 0 : 1);
}
void Sseg::updateSeg(void) {
char i,data,mask;
if( (++_dig) >= _numOfDigs)
_dig = 0;
data = _buffer[_dig];
mask = 0x80;
for(i=0;i<8;i++){
if(data & mask){
_segPins[i]->write(((_kcommon) || (_sinkDriver)) ? 1 : 0);
}else{
_segPins[i]->write(((_kcommon) || (_sinkDriver)) ? 0 : 1);
}
mask >>= 1;
}
}
bool Sseg::update(void) {
int t = timer.read_us();
bool sync = false;
if((t - _lastUpdateTime) > _updateInterval){
turnOff();
updateSeg();
turnOn();
_lastUpdateTime = t;
sync = (_dig == 0);
}
return sync;
}
void Sseg::updateWithDelay(int ms) {
timer.reset(); // to avoid overflow 32bit counter (~=30min)
int start = timer.read_ms();
do {
bool sync = update();
if(sync){
int t = timer.read_ms();
if((t - start) >= ms){
break;
}
}
} while(1);
}
void Sseg::updateOnce(void) {
uint8_t i;
_dig = _numOfDigs - 1;
turnOff();
for (i = 0 ; i < _numOfDigs ; i++) {
updateSeg();
turnOn();
wait(0.001f); // wait 1ms
turnOff();
}
}
// EOF
Yoshitaka Kuwata