diff --git a/README.md b/README.md index 5716b9b..e24b217 100644 --- a/README.md +++ b/README.md @@ -26,3 +26,12 @@ If the flash fails, try to add `--slow` before the `--port` argument (should not The tool also allows reading and erasing the chip, figure that out on your own if you need that (although `tulflash --help` might guide you if you ask it nicely). +## Example program + +You'll need to clone this repo (or just [download the file](example.c)) and install SDCC: + +``` +sdcc example.c +tulflash --port ... write example.ihx +``` + diff --git a/example.c b/example.c new file mode 100644 index 0000000..e6fe64f --- /dev/null +++ b/example.c @@ -0,0 +1,364 @@ +//********************************************************************** +//********************************************************************** +//*** *** +//*** K O P Y T O V1.1 *** +//*** *** +//*** vandalizoval Michal Procházka *** +//*** *** +//********************************************************************** +//********************************************************************** + +#include <8051.h> +#include +#include + +#define TickPerSec 100 +#define NPER (0x10000-(20000000L/12/TickPerSec)) + +// Definice vstupu a vystupu +#define _P0 0x80 +#define _P1 0x90 +#define _P2 0xa0 +#define _P3 0xb0 +#define _P4 0xc0 + +#define Tlac1 P3_2 +#define Tlac2 P3_3 +#define Buzzer P3_6 +#define LED1 P4_2 +#define LED2 P4_3 +#define LED3 P4_4 + +#define POT P1_0 +#define SMT P1_1 +#define ZAR P1_2 +#define LB_Data P1_3 +#define LB_SCK P1_4 +#define LB_SCL P1_5 +#define LB_RCK P1_6 +#define LB_OE P1_7 + +// TIMER se odecita v casovem preruseni +volatile uint16_t TIMER; +uint8_t LCD_Pos; + +/*************************************************************************\ +* LCD - Liquid Crystal Display * +*-------------------------------------------------------------------------* +* Description : Header file for programming of LCD display based on * +* HITACHI controller HD44780. * +*-------------------------------------------------------------------------* +* Author : Ceba & www.HW.cz Email : ceba@hw.cz * +* Developed : 06.02.2002 Last Update : 12.04.2003 * +* Version : 0.1.0 * +*-------------------------------------------------------------------------* +* Compiler : ANY Version: ANY * +* Source file : LCD.H * +*-------------------------------------------------------------------------* +* Target system : Charon II. - ATmega128, Quartz 14.7456 MHz * +* LCD SC1602A - 4.bit mode * +*-------------------------------------------------------------------------* +* Instruction D7 D6 D5 D4 D3 D2 D1 D0 * +* ============================================== * +* Display clear 0 0 0 0 0 0 0 1 * +* Cursor home 0 0 0 0 0 0 1 * * +* Entry Mode Set 0 0 0 0 0 1 I/D S * +* Display On/Off 0 0 0 0 1 D C B * +* Curs/Disp shift 0 0 0 1 S/C R/L * * * +* Function Set 0 0 1 DL N F * * * +* CG RAM addr set 0 1 ---------Acg--------- * +* DD RAM addr set 1 -------------Add--------- * +* * +* Meaning: * +* * - nonvalid bit * +* Acg - CG RAM address (CHARACTER GENERATOR) * +* Add - DD RAM address (DATA DISPLAY) * +* AC - adress counter * +* * +* I/D - 1-increment, 0-decrement * +* S - 1-display shift, 0-no display shift * +* D - 1-display ON, 0-display OFF * +* C - 1-cursor ON, 0-cursor OFF * +* B - 1-blink ON, 0-blink OFF * +* S/C - 1-display shift, 0-cursor movement * +* R/L - 1-right shift, 0-left shift * +* DL - 1-8 bits data transfer, 0-4 bits data transfer * +* N - 1-1/16 duty, 0-1/8 or 1/11 duty * +* F - 1-5x10 dot matrix, 0-5x7 dot matrix * +* BF - 1-internal operation in progress, 0-display ready * +* * +\*************************************************************************/ + +#define LCD_RS_PIN P2_4 +#define LCD_RW_PIN P2_5 +#define LCD_EN_PIN P2_6 + +#define LCD_RS 0x10 /* rgister select */ +#define LCD_RW 0x20 /* read/write */ +#define LCD_EN 0x40 /* chip enable */ + +/* --- LCD commands --- */ + +#define cmd_lcd_init 0x38 + +#define cmd_lcd_clear 0x01 +#define cmd_lcd_home 0x02 + +#define cmd_cur_shift_on 0x06 +#define cmd_cur_shift_off 0x07 + +#define cmd_lcd_on 0x0E +#define cmd_lcd_off 0x0A + +#define cmd_cur_on 0x0E +#define cmd_cur_off 0x0C + +#define cmd_cur_blink_on 0x0F +#define cmd_cur_blink_off 0x0E + +#define cmd_cur_left 0x10 +#define cmd_cur_right 0x14 + +#define cmd_scr_left 0x18 +#define cmd_scr_right 0x1C + +#define cmd_set_cgram_addr 0x40 +#define cmd_set_ddram_addr 0x80 + +void Delay(int pause) { + TIMER = 1 + pause; + while(TIMER); +} + +void LCD_Pause(void) { + // Hnus, ale funguje to + int i = 30; + while(i--); +} + +uint8_t LCD_State(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; +} + +void LCD_SendCmd( 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_State() & 0x80); +} + +void LCD_SendData(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_State() & 0x80); +} + +void LCD_Clear(void) { + LCD_SendCmd(0x01); /* display clear */ + LCD_Pos=0; +} + +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_SendCmd(0x28); /* 4 bit mode, 1/16 duty, 5x8 font */ + LCD_SendCmd(0x08); /* display off */ + LCD_Clear(); + LCD_SendCmd(0x06); /* entry mode */ + LCD_SendCmd(0x0C); /* display on, blinking cursor off */ +} + +int putchar(int c) { + if(c == 10) { + while((LCD_Pos != 0) && (LCD_Pos != 40)) { + LCD_SendData(32); + LCD_Pos++; + if(LCD_Pos == 80) LCD_Pos=0; + } + } else { + LCD_SendData(c); + LCD_Pos++; + if(LCD_Pos == 80) LCD_Pos=0; + } + + return 0; +} + +/***************************************** + ** Nastaveni preruseni ** + *****************************************/ + +/* Seriove preruseni a timer1 jsou nastaveny + na 115200bps, timer0 se nastavuje pomoci TH0.*/ +void init_interrupts(void) { + TMOD=0x21; + TCON=0x50; + PCON=0x80; + TL0=(uint8_t)NPER; + TH0=(uint8_t)(NPER >> 8); + IE=0x82; +} + +/***************************************** + ** Obsluha LED baru ** + *****************************************/ +/* +__sbit __at _P1+3 LB_Data; +__sbit __at _P1+4 LB_SCK; +__sbit __at _P1+5 LB_SCL; RESET +__sbit __at _P1+6 LB_RCK; PREPIS +__sbit __at _P1+7 LB_OE; +*/ + +void SetLedBar(uint16_t n) { + uint8_t i; + LB_RCK = 0; + LB_SCL = 0; + LB_SCL = 1; + LB_SCK = 0; + + for(i = 0; i < 10; i++) { + LB_Data = !(n & 1); + n >>= 1; // n = n >> 1 + LB_SCK = 1; + LB_SCK = 0; + } + + LB_RCK = 1; + LB_OE = 0; +} + +/***************************************** + ** Obsluha Klavesnice ** + *****************************************/ + +#define KEY_C_1 P0_0 +#define KEY_C_2 P0_1 +#define KEY_C_3 P0_2 +#define KEY_C_4 P0_3 + +#define KEY_R_1 P0_4 +#define KEY_R_2 P0_5 +#define KEY_R_3 P0_6 +#define KEY_R_4 P0_7 + +char GetKeyboard(void) { + P0 = 0xFF; + KEY_R_1 = 0; + LCD_Pause(); + if (!KEY_C_1) return '1'; + if (!KEY_C_2) return '2'; + if (!KEY_C_3) return '3'; + if (!KEY_C_4) return 'A'; + + P0 = 0xFF; + KEY_R_2 = 0; + LCD_Pause(); + if (!KEY_C_1) return '4'; + if (!KEY_C_2) return '5'; + if (!KEY_C_3) return '6'; + if (!KEY_C_4) return 'B'; + + P0 = 0xFF; + KEY_R_3 = 0; + LCD_Pause(); + if (!KEY_C_1) return '7'; + if (!KEY_C_2) return '8'; + if (!KEY_C_3) return '9'; + if (!KEY_C_4) return 'C'; + + P0 = 0xFF; + KEY_R_4 = 0; + LCD_Pause(); + if (!KEY_C_1) return '*'; + if (!KEY_C_2) return '0'; + if (!KEY_C_3) return '#'; + if (!KEY_C_4) return 'D'; + + return -1; +} + +/***************************************** + ** Hlavni program ** + *****************************************/ + +void main(void) { + init_interrupts(); + LCD_Init(); + + int i = 0; + + while(1) { + LCD_Clear(); + printf("hellOwOrld! %d", ++i); + Delay(TickPerSec); + } +} + +/***************************************** + ** Obsluha casovace 0 ** + *****************************************/ + + +void timer0(void) __interrupt(1) { + // Reload, 10ms + TL0=(uint8_t)NPER; + TH0=(uint8_t)(NPER >> 8); + if(TIMER!=0) TIMER--; +} +