//********************************************************************** //********************************************************************** //*** *** //*** K O P Y T O V1.1 *** //*** *** //*** vandalized by Michal Procházka *** //*** *** //********************************************************************** //********************************************************************** #include #include #include #define TICK_RATE 100 #define NPER (0x10000 - (20000000 / 6 / TICK_RATE)) // I/O definitions #define BUTTON_1 P3_2 #define BUTTON_2 P3_3 #define PIEZO P3_6 #define LED_RED P4_2 #define LED_YELLOW P4_3 #define LED_GREEN P4_4 #define POT P1_0 #define THERM P1_1 #define BULB P1_2 #define BAR_DAT P1_3 #define BAR_SCK P1_4 #define BAR_SCL P1_5 #define BAR_RCK P1_6 #define BAR_OE P1_7 #define LCD_RS_PIN P2_4 #define LCD_RW_PIN P2_5 #define LCD_EN_PIN P2_6 #define KEY_COL_1 P0_0 #define KEY_COL_2 P0_1 #define KEY_COL_3 P0_2 #define KEY_COL_4 P0_3 #define KEY_ROW_1 P0_4 #define KEY_ROW_2 P0_5 #define KEY_ROW_3 P0_6 #define KEY_ROW_4 P0_7 volatile uint16_t TIMER; // Timer-based delay, waits for pause * 10 ms void delay(int pause) { TIMER = 1 + pause; while(TIMER); } uint8_t lcd_pos; #define LCD_RS 0x10 /* rgister select */ #define LCD_RW 0x20 /* read/write */ #define LCD_EN 0x40 /* chip enable */ // Quick'n'dirty CPU pause, just enough for the LCD to stabilize. void lcd_pause(void) { __asm__ ("nop"); } // Reads the status register from the LCD. uint8_t lcd_read_status(void) { uint8_t temp; lcd_pause(); P2 = LCD_RW | 0x0F; lcd_pause(); LCD_EN_PIN = 1; lcd_pause(); temp = (P2 & 0x0F) << 4; LCD_EN_PIN = 0; lcd_pause(); LCD_EN_PIN = 1; lcd_pause(); temp = temp + (P2 & 0x0F); LCD_EN_PIN = 0; return temp; } // Writes a command to the LCD. void lcd_send_cmd( uint8_t val ) { lcd_pause(); P2 = (val >> 4) & 0x0F; lcd_pause(); LCD_EN_PIN = 1; lcd_pause(); LCD_EN_PIN = 0; lcd_pause(); P2 = (val & 0x0F); lcd_pause(); LCD_EN_PIN = 1; lcd_pause(); LCD_EN_PIN = 0; while(lcd_read_status() & 0x80); } // Writes a data value to the LCD. void lcd_send_data(uint8_t val) { lcd_pause(); P2 = LCD_RS | ((val >> 4) & 0x0F); lcd_pause(); LCD_EN_PIN = 1; lcd_pause(); LCD_EN_PIN = 0; lcd_pause(); P2 = LCD_RS | (val & 0x0F); lcd_pause(); LCD_EN_PIN = 1; lcd_pause(); LCD_EN_PIN = 0; while(lcd_read_status() & 0x80); } // Clears the LCD. void lcd_clear(void) { lcd_send_cmd(0x01); /* display clear */ lcd_pos = 0; } // Initializes the LCD. void lcd_init(void) { P2 = 0; /* set RS, RW and EN low */ /* all delays are vital */ delay(50); /* power on delay - wait more than 15 ms */ for(uint8_t i = 0; i < 3; i++) { P2 = 0x03; /* lce enable low */ delay(1); /* wait more than 100us */ P2 = LCD_EN | 0x03; /* lcd enable high */ delay(1); /* wait more than 100us */ P2 = 0x03; /* lce enable low */ delay(5); /* wait more than 4.1 ms */ } P2 = 0x02; /* lcd enable low */ delay(1); /* wait more than 100us */ P2 = LCD_EN | 0x02; /* lcd enable high */ delay(1); /* wait more than 100us */ P2 = 0x02; /* lcd enable low */ delay(5); /* wait more than 100us */ lcd_send_cmd(0x28); /* 4 bit mode, 1/16 duty, 5x8 font */ lcd_send_cmd(0x08); /* display off */ lcd_clear(); lcd_send_cmd(0x06); /* entry mode */ lcd_send_cmd(0x0C); /* display on, blinking cursor off */ } // Puts a character to the LCD. Correctly handles '\n'. void lcd_putchar(char c) { if(c == 10) { if(lcd_pos < 40) lcd_pos = 40; else lcd_pos = 0; } else { lcd_send_data(c); lcd_pos++; if(lcd_pos == 80) lcd_pos=0; } } // Initializes the background tick timer (for delays). void timer_init(void) { CKCON0 = X2; // Enable 2x clock mode // Initialize timer 0 as 16-bit countdown, timer 1 as 8-bit auto-reload countdown TMOD = 0x21; TCON = 0x50; // Initialize timer 0 for 100 Hz TL0 = (uint8_t)NPER; TH0 = (uint8_t)(NPER >> 8); // Enable interrupts only for timer 0 EA = 1; ET0 = 1; } // Initializes the serial port (along with timer 2). void serial_init(void) { // Initialize timer 2 as 312500 Hz as the baud rate generator (for tulflash) RCAP2H = 0xFF; RCAP2L = 0xFC; T2CON = 0x34; // Initialize serial I/O SCON = 0x50; TI = 1; } // Writes a character to the serial port. void serial_putchar(char c) { while(TI == 0); SBUF = c; TI = 0; } __bit stdout_to_lcd = 0; __bit stdout_to_serial = 0; // Writes a character to standard output (LCD, serial or both). int putchar(int c) { if(stdout_to_lcd) { lcd_putchar(c); } if(stdout_to_serial) { serial_putchar(c); } return 0; } // Writes a 10-bit value to the LED bar. Bit 0 = bottom LED, bit 9 = top LED. void led_bar_set(uint16_t n) { uint8_t i; BAR_RCK = 0; BAR_SCL = 0; BAR_SCL = 1; BAR_SCK = 0; for(i = 0; i < 10; i++) { BAR_DAT = !(n & 1); n >>= 1; // n = n >> 1 BAR_SCK = 1; BAR_SCK = 0; } BAR_RCK = 1; BAR_OE = 0; } // Reads a character from the keypad. char keypad_read(void) { P0 = 0xFF; KEY_ROW_1 = 0; lcd_pause(); if (!KEY_COL_1) return '1'; if (!KEY_COL_2) return '2'; if (!KEY_COL_3) return '3'; if (!KEY_COL_4) return 'A'; P0 = 0xFF; KEY_ROW_2 = 0; lcd_pause(); if (!KEY_COL_1) return '4'; if (!KEY_COL_2) return '5'; if (!KEY_COL_3) return '6'; if (!KEY_COL_4) return 'B'; P0 = 0xFF; KEY_ROW_3 = 0; lcd_pause(); if (!KEY_COL_1) return '7'; if (!KEY_COL_2) return '8'; if (!KEY_COL_3) return '9'; if (!KEY_COL_4) return 'C'; P0 = 0xFF; KEY_ROW_4 = 0; lcd_pause(); if (!KEY_COL_1) return '*'; if (!KEY_COL_2) return '0'; if (!KEY_COL_3) return '#'; if (!KEY_COL_4) return 'D'; return -1; } void main(void) { timer_init(); lcd_init(); serial_init(); delay(1); stdout_to_serial = 1; stdout_to_lcd = 1; int i = 1; while(1) { lcd_clear(); printf("Hellorld! %d\n", i); led_bar_set(i); LED_RED = !(i & 1); LED_YELLOW = !(i & 2); LED_GREEN = !(i & 4); BULB = !(i & 8); i++; delay(TICK_RATE); } } void timer0_handler(void) __interrupt(1) { // Reload, 10ms TL0 = (uint8_t)NPER; TH0 = (uint8_t)(NPER >> 8); if(TIMER != 0) TIMER--; }