mirror of
https://github.com/travisgoodspeed/goodwatch
synced 2024-11-23 09:19:58 +00:00
3a68135163
Fixes a bug where the calculator won't display zero, even though it exists internally.
191 lines
4.4 KiB
C
191 lines
4.4 KiB
C
#include "lcd.h"
|
|
#include "lcdtext.h"
|
|
|
|
/* Digits look like this, and we index them with 0 being the
|
|
leftmost.
|
|
|
|
AAAAA
|
|
F B
|
|
F B
|
|
F B
|
|
GGGGG
|
|
E C
|
|
E C
|
|
E C
|
|
DDDDD dp
|
|
|
|
*/
|
|
|
|
//This maps the segments of each digit.
|
|
// A, B, C, D, E, F, G, dp digit
|
|
const int lcdmap[10][8]={
|
|
{0x0b04, 0x0b40, 0x0b20, 0x0b01, 0x0a10, 0x0a20, 0x0b02, 0x0b10}, //0
|
|
{0x0940, 0x0a04, 0x0a02, 0x0910, 0x0901, 0x0902, 0x0920, 0x0a01}, //1
|
|
{0x0804, 0x0840, 0x0820, 0x0801, 0x0710, 0x0720, 0x0802, 0x0810}, //2
|
|
{0x0640, 0x0704, 0x0702, 0x0610, 0x0601, 0x0602, 0x0620, 0x0701}, //3
|
|
{0x0504, 0x0540, 0x0520, 0x0501, 0x0410, 0x0420, 0x0502, 0x0510}, //4
|
|
{0x0c02, 0x0404, 0x0402, 0x0310, 0x0302, 0x0304, 0x0340, 0x0401}, //5
|
|
{0x0204, 0x0220, 0x0210, 0x0201, 0x0110, 0x0120, 0x0202, 0x0301}, //6
|
|
{0x0040, 0x0104, 0x0102, 0x0010, 0x0001, 0x0002, 0x0020, 0x0201}, //7
|
|
};
|
|
|
|
//These are the fragments of the day of the week: 0x0904, 0x0a40, 0x0c01
|
|
//0x0c10 is beyond the screen.
|
|
//0x0240 seems not to be wired to any visible segment.
|
|
|
|
enum lcdmappos {A=1, B=2, C=4, D=8, E=0x10, F=0x20, G=0x40, DP=0x80};
|
|
const int numfont[]={
|
|
A|B|C|D|E|F, //0
|
|
B|C, //1
|
|
A|B|G|E|D, //2
|
|
A|B|G|C|D, //3
|
|
F|G|B|C, //4
|
|
A|F|G|C|D, //5
|
|
A|F|G|E|C|D, //6
|
|
A|B|C, //7
|
|
A|B|C|D|E|F|G, //8
|
|
A|B|G|F|C|D, //9
|
|
A|F|B|G|E|C, //A
|
|
F|E|G|C|D, //B
|
|
A|F|E|D, //C
|
|
E|G|C|D|B, //D
|
|
A|F|E|G|D, //E
|
|
A|G|F|E //F
|
|
};
|
|
|
|
#define DRAWPOINT(todraw) lcdm[todraw>>8]|=todraw&0xFF
|
|
#define CLEARPOINT(todraw) lcdm[todraw>>8]&=~(todraw&0xFF)
|
|
|
|
//! Draws one LCD digit.
|
|
void lcd_digit(int pos, int digit){
|
|
int segments=numfont[digit];
|
|
int bit;
|
|
for(bit=0;bit<8;bit++){
|
|
if(segments&(1<<bit))
|
|
DRAWPOINT(lcdmap[pos][bit]);
|
|
else
|
|
CLEARPOINT(lcdmap[pos][bit]);
|
|
|
|
}
|
|
}
|
|
|
|
//! Draws a decimal number on the screen.
|
|
void lcd_number(long num){
|
|
static long bcd=0;
|
|
static long oldnum=0;
|
|
int i;
|
|
|
|
/* This conversion takes too long at 32kHz, so we cache the last
|
|
value for rendering. */
|
|
if(oldnum==num){
|
|
lcd_hex(bcd);
|
|
return;
|
|
}
|
|
|
|
/* Otherwise we convert it with expensive divisions. */
|
|
bcd=0;
|
|
oldnum=num;
|
|
for(i=0;i<8 && num;i++){
|
|
bcd|=((num%10)<<(4*i));
|
|
num/=10;
|
|
}
|
|
|
|
lcd_hex(bcd);
|
|
}
|
|
|
|
//! Draws hex on the screen.
|
|
void lcd_hex(long num){
|
|
/* So in an ideal world, we'd have characters arranged nicely into
|
|
LCDM[] bytes as some development tools do, but in the real world,
|
|
we're pretty much stuck with them as they are physically
|
|
arranged.
|
|
|
|
This function takes a buffer of eight hex characters and displays
|
|
them on the screen.
|
|
*/
|
|
int i;
|
|
|
|
|
|
/* There is some weird bug where a segment in the second digit can
|
|
be dropped when drawn left to right. I don't understand it, but
|
|
this works around it. --Travis
|
|
*/
|
|
|
|
//for(i=0;i<8;i++)
|
|
for(i=7;i>=0;i--)
|
|
lcd_digit(i,(num>>(4*i))&0xf);
|
|
}
|
|
|
|
|
|
//! Activates the colon. 2 for invert.
|
|
void setcolon(int on){
|
|
if(on==2) //Blink
|
|
lcdm[3]^=0x20;
|
|
else if(on==1) //On
|
|
lcdm[3]|=0x20;
|
|
else //Off
|
|
lcdm[3]&=~0x20;
|
|
}
|
|
|
|
//! Activates the am. 2 for invert.
|
|
void setam(int on){
|
|
if(on==2) //Blink
|
|
lcdm[0]^=0x04;
|
|
else if(on==1) //On
|
|
lcdm[0]|=0x04;
|
|
else //Off
|
|
lcdm[0]&=~0x04;
|
|
}
|
|
|
|
//! Activates the pm. 2 for invert.
|
|
void setpm(int on){
|
|
if(on==2) //Blink
|
|
lcdm[1]^=0x40;
|
|
else if(on==1) //On
|
|
lcdm[1]|=0x40;
|
|
else //Off
|
|
lcdm[1]&=~0x40;
|
|
}
|
|
|
|
//! Activates the mult sign. 2 for invert.
|
|
void setmult(int on){
|
|
if(on==2) //Blink
|
|
lcdm[4]^=0x40;
|
|
else if(on==1) //On
|
|
lcdm[4]|=0x40;
|
|
else //Off
|
|
lcdm[4]&=~0x40;
|
|
}
|
|
|
|
//! Activates the minus sign. 2 for invert.
|
|
void setminus(int on){
|
|
if(on==2) //Blink
|
|
lcdm[6]^=0x04;
|
|
else if(on==1) //On
|
|
lcdm[6]|=0x04;
|
|
else //Off
|
|
lcdm[6]&=~0x04;
|
|
}
|
|
|
|
//! Activates the plus sign. 2 for invert.
|
|
void setplus(int on){
|
|
if(on==2) //Blink
|
|
lcdm[7]^=0x40;
|
|
else if(on==1) //On
|
|
lcdm[7]|=0x40;
|
|
else //Off
|
|
lcdm[7]&=~0x40;
|
|
}
|
|
|
|
//! Activates the divide sign. 2 for invert.
|
|
void setdivide(int on){
|
|
if(on==2) //Blink
|
|
lcdm[0xc]^=0x04;
|
|
else if(on==1) //On
|
|
lcdm[0xc]|=0x04;
|
|
else //Off
|
|
lcdm[0xc]&=~0x04;
|
|
}
|
|
|
|
|