Sadaf
Newbie level 5
- Joined
- Feb 7, 2003
- Messages
- 9
- Helped
- 10
- Reputation
- 20
- Reaction score
- 10
- Trophy points
- 1,283
- Location
- Lahore, Pakistan
- Activity points
- 824
tekton said:hi friends
I need to build an floor indicator with two 5x7 moving number
but with pic 16f84
glenjoy said:Questions:
1. How many 5x7 can it support?
2. Can the scroll be controleld?
a. Can it be paused.
b. Can it Scroll from top to bottom or vice versa?
3. Can the FONT be controlled?
Thanks.
#include <90s8535.h>
#include <delay.h>
// led display
#define LED_RESET PORTB.0
#define LED_CLOCK PORTB.1
#define LED_DATA PORTB.4
#define SCROLL_DELAY 140 // multiple of 7 (use smaller numbers for faster scroll)
// keyboard
#define KBD_CLOCK PORTD.2 // to be used for host -> keyboard communication
#define KBD_DATA PIND.4
#define BUFF_SIZE 64
// lcd
#define LCD_RS PORTD.5
#define LCD_RW PORTD.6
#define LCD_E PORTD.7
#define COMMAND_MODE 0
#define DATA_MODE 1
#define WRITE_MODE 0
#define READ_MODE 1
#define LCD_DATA_PORT PORTC
// functions
void lcd_init(void);
void lcd_clear(void);
void lcd_putc(unsigned char);
void lcd_putsf(unsigned char flash *);
void lcd_puts(unsigned char *str);
interrupt [EXT_INT0] keyboard_isr(void);
void put_char_kbbuff(unsigned char);
void put_scancode_kbbuff(unsigned char);
int getchar(void);
int kbhit(void);
void decode(unsigned char);
// global variables ***************************
unsigned char kb_buffer[BUFF_SIZE];
unsigned char bitcount;
unsigned char *inpt, *outpt;
unsigned char buffcnt = 0;
// led character definitions
// 5 data columns + 1 space
// for each character
flash unsigned char led_chars[94][6] = {
0x00,0x00,0x00,0x00,0x00,0x00, // space
0x00,0x00,0xfa,0x00,0x00,0x00, // !
0x00,0xe0,0x00,0xe0,0x00,0x00, // "
0x28,0xfe,0x28,0xfe,0x28,0x00, // #
0x24,0x54,0xfe,0x54,0x48,0x00, // $
0xc4,0xc8,0x10,0x26,0x46,0x00, // %
0x6c,0x92,0xaa,0x44,0x0a,0x00, // &
0x00,0xa0,0xc0,0x00,0x00,0x00, // '
0x00,0x38,0x44,0x82,0x00,0x00, // (
0x00,0x82,0x44,0x38,0x00,0x00, // )
0x28,0x10,0x7c,0x10,0x28,0x00, // *
0x10,0x10,0x7c,0x10,0x10,0x00, // +
0x00,0x0a,0x0c,0x00,0x00,0x00, // ,
0x10,0x10,0x10,0x10,0x10,0x00, // -
0x00,0x06,0x06,0x00,0x00,0x00, // .
0x04,0x08,0x10,0x20,0x40,0x00, // /
0x7c,0x8a,0x92,0xa2,0x7c,0x00, // 0
0x00,0x42,0xfe,0x02,0x00,0x00, // 1
0x42,0x86,0x8a,0x92,0x62,0x00, // 2
0x84,0x82,0xa2,0xd2,0x8c,0x00, // 3
0x18,0x28,0x48,0xfe,0x08,0x00, // 4
0xe5,0xa2,0xa2,0xa2,0x9c,0x00, // 5
0x3c,0x52,0x92,0x92,0x0c,0x00, // 6
0x80,0x8e,0x90,0xa0,0xc0,0x00, // 7
0x6c,0x92,0x92,0x92,0x6c,0x00, // 8
0x60,0x92,0x92,0x94,0x78,0x00, // 9
0x00,0x6c,0x6c,0x00,0x00,0x00, // :
0x00,0x6a,0x6c,0x00,0x00,0x00, // ;
0x10,0x28,0x44,0x82,0x00,0x00, // <
0x28,0x28,0x28,0x28,0x28,0x00, // =
0x00,0x82,0x44,0x28,0x10,0x00, // >
0x40,0x80,0x8a,0x90,0x60,0x00, // ?
0x4c,0x92,0x9e,0x82,0x7c,0x00, // @
0x7e,0x88,0x88,0x88,0x7e,0x00, // A
0xfe,0x92,0x92,0x92,0x6c,0x00, // B
0x7c,0x82,0x82,0x82,0x44,0x00, // C
0xfe,0x82,0x82,0x44,0x38,0x00, // D
0xfe,0x92,0x92,0x92,0x82,0x00, // E
0xfe,0x90,0x90,0x90,0x80,0x00, // F
0x7c,0x82,0x92,0x92,0x5e,0x00, // G
0xfe,0x10,0x10,0x10,0xfe,0x00, // H
0x00,0x82,0xfe,0x82,0x00,0x00, // I
0x04,0x02,0x82,0xfc,0x80,0x00, // J
0xfe,0x10,0x28,0x44,0x82,0x00, // K
0xfe,0x02,0x02,0x02,0x02,0x00, // L
0xfe,0x40,0x30,0x40,0xfe,0x00, // M
0xfe,0x20,0x10,0x08,0xfe,0x00, // N
0x7c,0x82,0x82,0x82,0x7c,0x00, // O
0xfe,0x90,0x90,0x90,0x60,0x00, // P
0x7c,0x82,0x8a,0x84,0x7a,0x00, // Q
0xfe,0x90,0x98,0x94,0x62,0x00, // R
0x62,0x92,0x92,0x92,0x8c,0x00, // S
0x80,0x80,0xfe,0x80,0x80,0x00, // T
0xfc,0x02,0x02,0x02,0xfc,0x00, // U
0xf8,0x04,0x02,0x04,0xf8,0x00, // V
0xfc,0x02,0x1c,0x02,0xfc,0x00, // W
0xc6,0x28,0x10,0x28,0xc6,0x00, // X
0xe0,0x10,0x0e,0x10,0xe0,0x00, // Y
0x86,0x8b,0x92,0xa2,0xc2,0x00, // Z
0x00,0xfe,0x82,0x82,0x00,0x00, // [
0x00,0x00,0x00,0x00,0x00,0x00, // *** do not remove this empty char ***
0x00,0x82,0x82,0xfe,0x00,0x00, // ]
0x20,0x40,0x80,0x40,0x20,0x00, // ^
0x02,0x02,0x02,0x02,0x02,0x00, // _
0x00,0x80,0x40,0x20,0x00,0x00, // `
0x04,0x2a,0x2a,0x2a,0x1e,0x00, // a
0xfe,0x12,0x22,0x22,0x1c,0x00, // b
0x1c,0x22,0x22,0x22,0x04,0x00, // c
0x1c,0x22,0x22,0x12,0xfe,0x00, // d
0x1c,0x2a,0x2a,0x2a,0x18,0x00, // e
0x10,0x7e,0x90,0x80,0x40,0x00, // f
0x30,0x4a,0x4a,0x4a,0x7c,0x00, // g
0xfe,0x10,0x20,0x20,0x1e,0x00, // h
0x00,0x22,0xbe,0x02,0x00,0x00, // i
0x04,0x02,0x22,0xbc,0x00,0x00, // j
0xfe,0x08,0x14,0x22,0x00,0x00, // k
0x00,0x82,0xfe,0x02,0x00,0x00, // l
0x3e,0x20,0x18,0x20,0x1e,0x00, // m
0x3e,0x10,0x20,0x20,0x1e,0x00, // n
0x1c,0x22,0x22,0x22,0x1c,0x00, // o
0x3e,0x28,0x28,0x28,0x10,0x00, // p
0x10,0x28,0x28,0x18,0x3e,0x00, // q
0x3e,0x10,0x20,0x20,0x10,0x00, // r
0x12,0x2a,0x2a,0x2a,0x04,0x00, // s
0x20,0xfc,0x22,0x02,0x04,0x00, // t
0x3c,0x02,0x02,0x04,0x3e,0x00, // u
0x38,0x04,0x02,0x04,0x38,0x00, // v
0x3c,0x02,0x0c,0x02,0x3c,0x00, // w
0x22,0x14,0x08,0x14,0x22,0x00, // x
0x30,0x0a,0x0a,0x0a,0x3c,0x00, // y
0x22,0x26,0x2a,0x32,0x22,0x00, // z
0x00,0x10,0x6c,0x82,0x00,0x00, // {
0x00,0x00,0xfe,0x00,0x00,0x00, // |
0x00,0x82,0x6c,0x10,0x00,0x00 }; // }
// keyboard scan codes (without & with shift key pressed)
flash unsigned char unshifted[67][2] = {
//0x0d,9,
0x0e,'`',0x15,'q',0x16,'1',0x1a,'z',0x1b,'s',0x1c,'a',0x1d,'w',0x1e,'2',0x21,'c',0x22,'x',0x23,'d',0x24,'e',
0x25,'4',0x26,'3',0x29,' ',0x2a,'v',0x2b,'f',0x2c,'t',0x2d,'r',0x2e,'5',0x31,'n',0x32,'b',0x33,'h',0x34,'g',
0x35,'y',0x36,'6',0x39,',',0x3a,'m',0x3b,'j',0x3c,'u',0x3d,'7',0x3e,'8',0x41,',',0x42,'k',0x43,'i',0x44,'o',
0x45,'0',0x46,'9',0x49,'.',0x4a,'/',0x4b,'l',0x4c,';',0x4d,'p',0x4e,'-',0x52,'`',0x54,'[',0x55,'=',0x5a,13,
0x5b,']',0x5d,'/',0x61,'<',0x66,8, 0x69,'1',0x6b,'4',0x6c,'7',0x70,'0',0x71,',',0x72,'2',0x73,'5',0x74,'6',
0x75,'8',0x79,'+',0x7a,'3',0x7b,'-',0x7c,'*',0x7d,'9',0,0 };
flash unsigned char shifted[67][2] = {
//0x0d,9,
0x0e,'`',0x15,'Q',0x16,'!',0x1a,'Z',0x1b,'S',0x1c,'A',0x1d,'W',0x1e,'@',0x21,'C',0x22,'X',0x23,'D',0x24,'E',
0x25,'$',0x26,'#',0x29,' ',0x2a,'V',0x2b,'F',0x2c,'T',0x2d,'R',0x2e,'%',0x31,'N',0x32,'B',0x33,'H',0x34,'G',
0x35,'Y',0x36,'^',0x39,'L',0x3a,'M',0x3b,'J',0x3c,'U',0x3d,'&',0x3e,'*',0x41,'<',0x42,'K',0x43,'I',0x44,'O',
0x45,')',0x46,'(',0x49,'>',0x4a,'?',0x4b,'L',0x4c,':',0x4d,'P',0x4e,'_',0x52,'"',0x54,'{',0x55,'+',0x5a,13,
0x5b,'}',0x5d,'|',0x61,'>',0x66,8, 0x69,'1',0x6b,'4',0x6c,'7',0x70,'0',0x71,',',0x72,'2',0x73,'5',0x74,'6',
0x75,'8',0x79,'+',0x7a,'3',0x7b,'-',0x7c,'*',0x7d,'9',0,0 };
//***********************************************
void main() {
int i,j;
unsigned char ch,row;
flash unsigned char *dataPtr, *tmpDataPtr;
unsigned char messageLength, currentChar, charOffset, tmpCurrentChar, tmpCharOffset, ledArray[23];
unsigned char message[308]; // 300 chars + 4 spaces at start and end of message
#asm("cli"); // disable all interrupts
// initialise ports
DDRA = 0xff; // port A output
DDRB = 0xff; // port B output
DDRC = 0xff; // port C output
DDRD = 0xeb; // pins 2 & 4 inputs
// initialise keyboard variables
inpt = kb_buffer;
outpt = kb_buffer;
buffcnt = 0;
bitcount = 11;
// initialise lcd
lcd_init();
// initialise LED display (shift registers)
LED_RESET = 0;
LED_CLOCK = 0;
LED_RESET = 1;
// initialise interrupt registers
GIMSK = 0x40; // enable INT0 interrupt
MCUCR = 0x02; // INT0 interrupt on falling edge
#asm("sei"); // enable all interrupts
while(1) {
ch = 0x00;
i = 0;
// fill the array with 4 empty spaces at the start and the end of the message
// as the screen has 4 chars
// (it looks better if we start scrolling with empty screen and end
// with empty screen , rather than displaying four chars immediatelly and
// then start scrolling)
message[i++] = ' ';
message[i++] = ' ';
message[i++] = ' ';
message[i++] = ' ';
// enter message until 300 characters entered or <enter> key pressed
while((ch != 13) || (i < 308)) {
ch = getchar();
if ((ch != 13) && (ch != 'q')) {
lcd_putc(ch);
message[i++] = ch;
}
// if q is pressed clear the LCD
// (code only writes to the first LCD line so
// if the line is longer than 16 chars i cant see the rest of the chars
// , there will be a menu system in the future software version
// and the line on the LCD will be scrolled
// to the left automatically as the cursor gets to the end of the line
//, for now use this dirty solution:))
if (ch == 'q')
lcd_clear();
}
message[i++] = ' ';
message[i++] = ' ';
message[i++] = ' ';
message[i++] = ' ';
messageLength = i - 4;
charOffset = 0;
currentChar = 0;
dataPtr = &led_chars[message[0] - 0x20][0];
// this loop is the heart of the scroll
// message is scrolled until a key is hit on the keyboard
while (!kbhit()) {
// load led array
tmpDataPtr = dataPtr;
tmpCharOffset = charOffset;
tmpCurrentChar = currentChar;
for (i = 0; i <= 22; i++) {
ledArray[i] = *tmpDataPtr++;
if (++tmpCharOffset==0x06) {
tmpCharOffset = 0;
if (++tmpCurrentChar == messageLength)
tmpCurrentChar = 0;
tmpDataPtr = &led_chars[message[tmpCurrentChar] - 0x20][0];
}
}
if (++charOffset == 0x06) {
charOffset = 0;
if (++currentChar == messageLength)
currentChar = 0;
}
dataPtr = &led_chars[message[currentChar] - 0x20][charOffset];
// display led array
row = 0x02;
for (j = 0;j <= SCROLL_DELAY; j++) {
for (i = 0; i <= 22; i++) {
LED_DATA = (ledArray[i] & row) ? 1 : 0;
LED_CLOCK = 1;
LED_CLOCK = 0;
}
PORTA = row;
row <<= 1; // next line to be switched on
if (!row) // if last line go back to the first line
row = 0x02;
delay_us(800);
PORTA = 0x00;
}
}
lcd_clear();
}
}
//***********************************************
// return 1 if a key is pressed (non blocking)
// else return 0
int kbhit(void) {
if (buffcnt) {
// reset buffer variables (flush the buffer)
inpt = kb_buffer;
outpt = kb_buffer;
buffcnt = 0;
bitcount = 11;
return 1;
}
return 0;
}
// puts scan code (in hex format) into keyboard buffer
// (used for debugging purposes)
//***********************************************
void put_scancode_kbbuff(unsigned char sc) {
unsigned char h,l;
// convert hi and low nibbles of the scancode
// into ascii and store them into keyboard buffer
h = ((sc & 0xf0 ) >> 0x04) & 0x0f;
if ( h > 9)
h = h + 7;
h = h + 0x30;
put_char_kbbuff(h);
l = sc & 0x0f;
if ( l > 9)
l = l + 7;
l = l + 0x30;
put_char_kbbuff(l);
}
//***********************************************
// keyboard ISR
interrupt [EXT_INT0] keyboard_isr(void) {
static unsigned char data; // holds the received scan code
// function entered at falling edge of the kbd clock signal
// if data bit is the next bit to be read
// (bit 3 to 10 is data, start, stop & parity bis are ignored
if((bitcount < 11) && (bitcount > 2)) {
data = (data >> 1);
if (KBD_DATA) // if next bit is 1
data = data | 0x80; // store a '1'
else
data = data & 0x7f; // else store a '0'
}
if(--bitcount == 0) { // all bits received ?
decode(data); // decode received byte
bitcount = 11; // reset bit counter
}
}
//***********************************************
// decode scan code
void decode(unsigned char sc) {
static unsigned char is_up=0, shift = 0, mode = 0;
unsigned char i;
if (!is_up) {
switch (sc) {
case 0xF0 :// The up-key identifier
is_up = 1;
break;
case 0x12 :// Left SHIFT
shift = 1;
break;
case 0x59 :// Right SHIFT
shift = 1;
break;
case 0x05 :// F1
if(mode == 0)
mode = 1;// Enter scan code mode
if(mode == 2)
mode = 3;// Leave scan code mode
break;
default:
if(mode == 0 || mode == 3) {// If ASCII mode
if(!shift) {// If shift not pressed, do a table look-up
for(i = 0; unshifted[i][0]!=sc && unshifted[i][0]; i++);
if (unshifted[i][0] == sc) {
put_char_kbbuff(unshifted[i][1]);
}
}
else {// If shift pressed
for(i = 0; shifted[i][0]!=sc && shifted[i][0]; i++);
if (shifted[i][0] == sc) {
put_char_kbbuff(shifted[i][1]);
}
}
}
else put_scancode_kbbuff(sc); // scan code mode (debugging mode)
break;
}
}
else {
is_up = 0;// Two 0xF0 in a row not allowed
switch (sc) {
case 0x12 :// Left SHIFT
shift = 0;
break;
case 0x59 :// Right SHIFT
shift = 0;
break;
case 0x05 :// F1 -- F1 puts you in debugging mode
// pressing F1 again gets you out of debugging mode
// in debugging mode hex code of the scan codes
// are stored in the buffer instead of their ascii codes
if(mode == 1)
mode = 2;
if(mode == 3)
mode = 0;
break;
}
}
}
//***********************************************
// store character in the keyboard ring buffer
void put_char_kbbuff(unsigned char c) {
if (buffcnt < BUFF_SIZE) { // if buffer is not full
*(inpt++) = c;
buffcnt++;
if (inpt >= kb_buffer + BUFF_SIZE) // pointer wrapping
inpt = kb_buffer;
}
}
//***********************************************
// get next available character from the keyboard ring buffer
// (waits until a character is available in the buffer)
int getchar(void) {
int byte;
while (buffcnt == 0); // wait for data
byte = *outpt; // get byte
outpt++;
if (outpt >= kb_buffer + BUFF_SIZE) // pointer wrapping
outpt = kb_buffer;
buffcnt--; // decrement buffer count
return byte;
}
//***********************************************
void lcd_init(void) {
delay_ms(50);
LCD_E = 0;
LCD_RS = COMMAND_MODE;
LCD_RW = WRITE_MODE;
delay_ms(1);
LCD_DATA_PORT = 0x38; // 8 bit, 2 lines, 5x8 font
LCD_E = 1; delay_ms(1);
LCD_E = 0; delay_ms(1);
LCD_DATA_PORT = 0x0f; // display & cursor ON, blink & underlined
LCD_E = 1; delay_ms(1);
LCD_E = 0; delay_ms(2);
lcd_clear();
}
//***********************************************
void lcd_clear(void) {
LCD_RS = COMMAND_MODE;
LCD_DATA_PORT = 0x01; // clear display
LCD_E = 1; delay_ms(1);
LCD_E = 0; delay_ms(2);
}
//***********************************************
// display char on lcd
void lcd_putc(unsigned char ch) {
LCD_RS = DATA_MODE;
LCD_DATA_PORT = ch;
LCD_E = 1; delay_us(40);
LCD_E = 0; delay_us(40);
}
//***********************************************
// display string on lcd
// input: pointer to string stored in flash ROM
void lcd_putsf(unsigned char flash *str) {
while (*str!= '\0') {
lcd_putc(*(str++));
}
}
//************************************************
// same as above except the string is in RAM
void lcd_puts(unsigned char *str) {
while (*str!= '\0') {
lcd_putc(*(str++));
}
}
glenjoy said:Are you also using MAX7219?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?