/* $ avr-gcc -Werror -mmcu=atmega162 -Os -o test_lcd.elf -DF_CPU=1000000 -Wall -Waddr-space-convert -include $AVRTEST/avrtest.h test_lcd.c $AVRTEST/exit-atmega162.o $ avr-objdump -h -d -S -r -j .text -j .data -j .rodata -j .eeprom -j .boot test_lcd.elf > test_lcd.lst $ avr-objdump -P mem-usage test_lcd.elf test_lcd.elf: file format elf32-avr AVR Memory Usage ---------------- Device: atmega162 Program: 2512 bytes (15.3% Full) (.text + .data + .rodata + .bootloader) Data: 38 bytes (3.7% Full) (.data + .bss + .noinit) $ avrtest -mmcu=avr5 test_lcd.elf gestartet lcd_clrscr() @LCD(0,0): 0 Testzeile 1 @LCD(0,1): 0 Testzeile 2 @LCD(0,2): 0 Testzeile 3 @LCD(0,3): 0 Testzeile 4anzeige_version() lcd_clrscr() @LCD(0,0): 1 Testzeile 1 @LCD(0,1): 1 Testzeile 2 @LCD(0,2): 1 Testzeile 3 @LCD(0,3): 1 Testzeile 4eingabe_betrieb() lcd_clrscr() @LCD(0,0): 1 Testzeile 1 @LCD(0,1): 1 Testzeile 2 @LCD(0,2): 1 Testzeile 3 @LCD(0,3): 1 Testzeile 4eingabe_betrieb() lcd_clrscr() @LCD(0,0): 1 Testzeile 1 @LCD(0,1): 1 Testzeile 2 @LCD(0,2): 1 Testzeile 3 @LCD(0,3): 1 Testzeile 4eingabe_betrieb() lcd_clrscr() @LCD(0,0): 1 Testzeile 1 @LCD(0,1): 1 Testzeile 2 @LCD(0,2): 1 Testzeile 3 @LCD(0,3): 1 Testzeile 4eingabe_betrieb() exit status: EXIT reason: exit 0 function called program: test_lcd.elf exit address: 0009b0 total cycles: 10015462 total instr.: 8009073 */ #include #include #include #include #include #include #ifdef AVRTEST_H #include // PSTR #include #endif #define UART_BAUD_RATE 9600 // 9600 baud #define NEXT_STATE 1 #define PREVIOUS_STATE 0 #define LCD_LINES 4 #define LCD_DISP_LENGTH 20 #define LCD_IO_DATA 0xC000 // A15=1, A14=0 ==> Instruction Register #define LCD_IO_FUNCTION 0x8000 static int8_t anzeige_version(void) { #ifdef AVRTEST_H LOG_PSTR (PSTR("anzeige_version()")); #endif _delay_ms(2000); return NEXT_STATE; } static int8_t eingabe_betrieb(void) { #ifdef AVRTEST_H LOG_PSTR (PSTR("eingabe_betrieb()")); #endif _delay_ms(2000); return NEXT_STATE; } #define FLIT(X) ((const __flash char[]) { X } ) // AVR-LibC v2.3 typedef struct menu { const __flash char *texte[LCD_LINES]; const int8_t previous; const int8_t next; int8_t (*fp) (void); } t_menu; const __flash t_menu main_menu[] = { { { FLIT(" 0 Testzeile 1"), FLIT(" 0 Testzeile 2"), FLIT(" 0 Testzeile 3"), FLIT(" 0 Testzeile 4") }, 0, 1, anzeige_version }, { { FLIT(" 1 Testzeile 1"), FLIT(" 1 Testzeile 2"), FLIT(" 1 Testzeile 3"), FLIT(" 1 Testzeile 4") }, 1, 1, eingabe_betrieb } }; static inline void lcd_write (uint8_t d, bool rs) { #ifdef AVRTEST_H LOG_PFMT_U8 (isprint (d) ? PSTR("%c") : PSTR("{0x%02x}"), d); #endif if (rs) *(volatile uint8_t*)(LCD_IO_DATA) = d; else *(volatile uint8_t*)(LCD_IO_FUNCTION) = d; } void lcd_putc (char c) { lcd_write (c, 1); } void lcd_puts_p (const __flash char *pstr) // print string from program memory on lcd (no auto linefeed) { char c; while ((c = *pstr++)) { lcd_putc (c); } } void lcd_clrscr (void) { #ifdef AVRTEST_H LOG_PSTR (PSTR ("\nlcd_clrscr()")); #endif } void lcd_gotoxy (uint8_t x, uint8_t y) { #ifdef AVRTEST_H LOG_PFMT_U8 (PSTR ("\n@LCD(%u,"), x); LOG_PFMT_U8 (PSTR ("%u):"), y); #endif } void show_display_lines (const __flash t_menu *menu) { lcd_clrscr(); const __flash char *const __flash *texte = & menu->texte[0]; for (int i = 0; i < LCD_LINES; i++) { lcd_gotoxy (0, i); lcd_puts_p (*texte++); } } int main(void) { int index, new_index; DDRB |= (1 << PB3) | (1 << PB2) | (1 << PB1) | (1 << PB0); PORTB = (1 << PB3) | (1 << PB2) | (1 << PB1) | (1 << PB0); PORTB ^= (1 << PB0); PORTB ^= (1 << PB1); printf_P (PSTR("gestartet\n")); index = 0; for (;;) { for (;;) { const __flash t_menu *menu = &main_menu[index]; show_display_lines (menu); new_index = menu->fp(); if (new_index == 0) index = menu->previous; else index = menu->next; #ifdef AVRTEST_H static int count; if (++count > 4) return 0; #endif } } }