--- /dev/null
+#
+# Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
+#
+# This file is part of simavr.
+#
+# simavr is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# simavr is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with simavr. If not, see <http://www.gnu.org/licenses/>.
+
+board= charlcd
+firm_src = ${wildcard at*${board}.c}
+firmware = ${firm_src:.c=.axf}
+simavr = ../../
+
+SHELL = /bin/bash
+
+IPATH = .
+IPATH += ../parts
+IPATH += ${simavr}/include
+IPATH += ${simavr}/simavr/sim
+
+VPATH = .
+VPATH += ../parts
+
+LDFLAGS += -lpthread
+LDFLAGS += -lGLU
+LDFLAGS += -lGL
+LDFLAGS += `sdl-config --libs`
+LDFLAGS += -lSDL_image
+
+CFLAGS = `sdl-config --cflags`
+#ifneq (${shell uname}, Darwin)
+#else
+#LDFLAGS += -framework GLUT -framework OpenGL
+#endif
+all: obj atmega48_charlcd.axf ${board}
+
+atmega48_charlcd.axf: atmega48_charlcd.c atmega48_lcd.c atmega48_lcd.h
+ @echo AVR-CC ${<}
+ ${AVR}gcc -Wall -gdwarf-2 -Os -std=gnu99 \
+ -mmcu=atmega48 \
+ -DF_CPU=8000000 \
+ -fno-inline-small-functions \
+ -ffunction-sections -fdata-sections \
+ -Wl,--relax,--gc-sections \
+ -Wl,--undefined=_mmcu,--section-start=.mmcu=0x910000 \
+ -I../include -I../../include \
+ atmega48_charlcd.c atmega48_lcd.c -o atmega48_charlcd.axf
+ @${AVR}size ${@}|sed '1d'
+
+include ${simavr}/Makefile.common
+
+${board} : ${OBJ}/ac_input.o
+${board} : ${OBJ}/hd44780.o
+${board} : ${OBJ}/hd44780_glut.o
+${board} : ${OBJ}/${board}.o
+ @echo LD $@
+ @gcc -MD ${CFLAGS} ${LFLAGS} -o $@ $^ $(LDFLAGS) ${simavr}/simavr/libsimavr.a
+
+clean:
+ rm -rf obj *.hex *.a *.axf ${board} *.vcd .*.swo .*.swp .*.swm .*.swn
--- /dev/null
+
+#include "sim_avr.h"
+#include "ac_input.h"
+#include "stdio.h"
+
+static avr_cycle_count_t switch_auto( struct avr_t * avr, avr_cycle_count_t when, void * param){
+ ac_input_t * b = (ac_input_t *)param;
+ b->value = b->value == 0 ? 1 : 0;
+ avr_raise_irq( b->irq + IRQ_AC_OUT, b->value );
+ return when + avr_usec_to_cycles(avr,10000);
+}
+
+void ac_input_init(struct avr_t *avr, ac_input_t *b){
+ b->irq = avr_alloc_irq(0,IRQ_AC_COUNT);
+ b->avr = avr;
+ b->value = 0;
+ avr_cycle_timer_register_usec(avr, 10000, switch_auto, b);
+}
--- /dev/null
+#ifndef __AC_INPUT_H__
+#define __AC_INPUT_H__
+
+#include "sim_irq.h"
+
+/*
+ * Simulates a 50hz changing signal
+ */
+
+enum {
+ IRQ_AC_OUT = 0,
+ IRQ_AC_COUNT
+};
+
+typedef struct ac_input_t {
+ avr_irq_t * irq;
+ struct avr_t * avr;
+ uint8_t value;
+} ac_input_t;
+
+void ac_input_init(struct avr_t * avr, ac_input_t * b);
+
+#endif
--- /dev/null
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <util/delay.h>
+#include "stdlib.h"
+#include "string.h"
+
+#include "atmega48_lcd.h"
+
+#include "avr_mcu_section.h"
+AVR_MCU(F_CPU, "atmega48");
+
+static uint8_t subsecct = 0;
+static uint8_t hour = 0;
+static uint8_t minute = 0;
+static uint8_t second = 0;
+static volatile uint8_t update_needed = 0;
+
+ISR( INT0_vect ){
+ /* External interrupt on pin D2 */
+ subsecct++;
+ if( subsecct == 50 ){
+ second++;
+ update_needed = 1;
+ if(second ==60){
+ minute++;
+ second = 0;
+ if(minute==60){
+ minute =0;
+ hour++;
+ if(hour==24) hour =0;
+ }
+ }
+ }
+}
+
+int main(){
+ lcd_init();
+
+
+ EICRA = (1<<ISC00);
+ EIMSK = (1<<INT0);
+
+ sei();
+
+ while(1)
+ {
+ while(!update_needed);
+ update_needed = 0;
+ char buffer[16];
+ lcd_clear();
+ set_cursor(4,1);
+ itoa(hour,buffer,10);
+ lcd_string(buffer);
+ lcd_data(':');
+ itoa(minute,buffer,10);
+ lcd_string(buffer);
+ lcd_data(':');
+ itoa(second,buffer,10);
+ lcd_string(buffer);
+ }
+
+}
--- /dev/null
+// Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus\r
+// http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung\r
+//\r
+// Die Pinbelegung ist über defines in lcd-routines.h einstellbar\r
+ \r
+#include <avr/io.h>\r
+#include "atmega48_lcd.h"\r
+#include <util/delay.h>\r
+ \r
+// sendet ein Datenbyte an das LCD\r
+ \r
+void lcd_data(unsigned char temp1)\r
+{\r
+ unsigned char temp2 = temp1;\r
+ \r
+ LCD_PORT |= (1<<LCD_RS); // RS auf 1 setzen\r
+ \r
+ temp1 = temp1 >> 4;\r
+ temp1 = temp1 & 0x0F;\r
+ LCD_PORT &= 0xF0;\r
+ LCD_PORT |= temp1; // setzen\r
+ lcd_enable();\r
+ \r
+ temp2 = temp2 & 0x0F;\r
+ LCD_PORT &= 0xF0;\r
+ LCD_PORT |= temp2; // setzen\r
+ lcd_enable();\r
+ \r
+ _delay_us(42);\r
+}\r
+ \r
+// sendet einen Befehl an das LCD\r
+ \r
+void lcd_command(unsigned char temp1)\r
+{\r
+ unsigned char temp2 = temp1;\r
+ \r
+ LCD_PORT &= ~(1<<LCD_RS); // RS auf 0 setzen\r
+ \r
+ temp1 = temp1 >> 4; // oberes Nibble holen\r
+ temp1 = temp1 & 0x0F; // maskieren\r
+ LCD_PORT &= 0xF0;\r
+ LCD_PORT |= temp1; // setzen\r
+ lcd_enable();\r
+ \r
+ temp2 = temp2 & 0x0F; // unteres Nibble holen und maskieren\r
+ LCD_PORT &= 0xF0;\r
+ LCD_PORT |= temp2; // setzen\r
+ lcd_enable();\r
+ \r
+ _delay_us(42);\r
+}\r
+ \r
+// erzeugt den Enable-Puls\r
+void lcd_enable(void)\r
+{\r
+ // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers einfügen\r
+ // http://www.mikrocontroller.net/topic/81974#685882\r
+ LCD_PORT |= (1<<LCD_EN);\r
+ _delay_us(1); // kurze Pause\r
+ // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers verlängern\r
+ // http://www.mikrocontroller.net/topic/80900\r
+ LCD_PORT &= ~(1<<LCD_EN);\r
+}\r
+ \r
+// Initialisierung: \r
+// Muss ganz am Anfang des Programms aufgerufen werden.\r
+ \r
+void lcd_init(void)\r
+{\r
+ LCD_DDR = LCD_DDR | 0x0F | (1<<LCD_RS) | (1<<LCD_EN); // Port auf Ausgang schalten\r
+ \r
+ // muss 3mal hintereinander gesendet werden zur Initialisierung\r
+ \r
+ _delay_ms(15);\r
+ LCD_PORT &= 0xF0;\r
+ LCD_PORT |= 0x03; \r
+ LCD_PORT &= ~(1<<LCD_RS); // RS auf 0\r
+ lcd_enable();\r
+ \r
+ _delay_ms(5);\r
+ lcd_enable();\r
+ \r
+ _delay_ms(1);\r
+ lcd_enable();\r
+ _delay_ms(1);\r
+ \r
+ // 4 Bit Modus aktivieren \r
+ LCD_PORT &= 0xF0;\r
+ LCD_PORT |= 0x02;\r
+ lcd_enable();\r
+ _delay_ms(1);\r
+ \r
+ // 4Bit / 2 Zeilen / 5x7\r
+ lcd_command(0x28);\r
+ \r
+ // Display ein / Cursor aus / kein Blinken\r
+ lcd_command(0x0C); \r
+ \r
+ // inkrement / kein Scrollen\r
+ lcd_command(0x06);\r
+ \r
+ lcd_clear();\r
+}\r
+ \r
+// Sendet den Befehl zur Löschung des Displays\r
+ \r
+void lcd_clear(void)\r
+{\r
+ lcd_command(CLEAR_DISPLAY);\r
+ _delay_ms(5);\r
+}\r
+ \r
+// Sendet den Befehl: Cursor Home\r
+ \r
+void lcd_home(void)\r
+{\r
+ lcd_command(CURSOR_HOME);\r
+ _delay_ms(5);\r
+}\r
+ \r
+// setzt den Cursor in Zeile y (1..4) Spalte x (0..15)\r
+ \r
+void set_cursor(uint8_t x, uint8_t y)\r
+{\r
+ uint8_t tmp;\r
+ \r
+ switch (y) {\r
+ case 1: tmp=0x80+0x00+x; break; // 1. Zeile\r
+ case 2: tmp=0x80+0x40+x; break; // 2. Zeile\r
+ case 3: tmp=0x80+0x10+x; break; // 3. Zeile\r
+ case 4: tmp=0x80+0x50+x; break; // 4. Zeile\r
+ default: return; // für den Fall einer falschen Zeile\r
+ }\r
+ lcd_command(tmp);\r
+}\r
+ \r
+// Schreibt einen String auf das LCD\r
+ \r
+void lcd_string(char *data)\r
+{\r
+ while(*data) {\r
+ lcd_data(*data);\r
+ data++;\r
+ }\r
+}\r
--- /dev/null
+#ifndef LCD_H\r
+#define LCD_H\r
+\r
+// Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus\r
+// http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung\r
+//\r
+void lcd_data(unsigned char temp1);\r
+void lcd_string(char *data);\r
+void lcd_command(unsigned char temp1);\r
+void lcd_enable(void);\r
+void lcd_init(void);\r
+void lcd_home(void);\r
+void lcd_clear(void);\r
+void set_cursor(uint8_t x, uint8_t y);\r
+ \r
+// Hier die verwendete Taktfrequenz in Hz eintragen, wichtig!\r
+ \r
+#define F_CPU 8000000\r
+ \r
+// LCD Befehle\r
+ \r
+#define CLEAR_DISPLAY 0x01\r
+#define CURSOR_HOME 0x02\r
+ \r
+// Pinbelegung für das LCD, an verwendete Pins anpassen\r
+ \r
+#define LCD_PORT PORTB\r
+#define LCD_DDR DDRB\r
+#define LCD_RS PB4\r
+#define LCD_EN PB5\r
+// DB4 bis DB7 des LCD sind mit PD0 bis PD3 des AVR verbunden\r
+\r
+#endif //LCD_H\r
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <libgen.h>
+
+#include "sim_avr.h"
+#include "avr_ioport.h"
+#include "sim_elf.h"
+#include "sim_gdb.h"
+#include "sim_vcd_file.h"
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <pthread.h>
+
+#include "SDL.h"
+#include "SDL_image.h"
+
+#include "ac_input.h"
+#include "hd44780.h"
+#include "hd44780_glut.h"
+
+/* screen width, height, and bit depth */
+#define SCREEN_WIDTH 800
+#define SCREEN_HEIGHT 600
+#define SCREEN_BPP 16
+
+int window;
+avr_t * avr = NULL;
+avr_vcd_t vcd_file;
+ac_input_t ac_input;
+hd44780_t hd44780;
+
+SDL_Surface *surface;
+
+static void * avr_run_thread( ){
+ while(1){
+ avr_run(avr);
+ }
+}
+
+void Quit( int returnCode )
+{
+ SDL_Quit( );
+ exit( returnCode );
+}
+
+int resizeWindow( int width, int height )
+{
+ if ( height == 0 ) height = 1;
+ glViewport( 0, 0, ( GLsizei )width, ( GLsizei )height );
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity( );
+ glOrtho(0, 800, 0, 600, 0, 10);
+
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity( );
+
+ return 1;
+}
+
+void handleKeyPress( SDL_keysym *keysym )
+{
+ switch ( keysym->sym )
+ {
+ case SDLK_ESCAPE:
+ Quit( 0 );
+ break;
+ case SDLK_F1:
+ SDL_WM_ToggleFullScreen( surface );
+ break;
+ default:
+ break;
+ }
+}
+
+int initGL( GLvoid )
+{
+ glEnable( GL_TEXTURE_2D );
+ glShadeModel( GL_SMOOTH );
+
+ glClearColor( 0.8f, 0.8f, 0.8f, 1.0f );
+ glColor4f( 1.0f,1.0f,1.0f,1.0f);
+ glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
+ glEnable( GL_BLEND);
+
+ glClearDepth( 1.0f );
+
+ glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
+
+ hd44780_gl_init();
+
+ return 1;
+}
+
+int drawGLScene( GLvoid )
+{
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+ glMatrixMode(GL_MODELVIEW); // Select modelview matrix
+ glPushMatrix();
+ glLoadIdentity(); // Start with an identity matrix
+ glScalef(3,3,1);
+ glTranslatef( 89.66f,150,0);
+ hd44780_gl_draw( &hd44780 );
+ glPopMatrix();
+ SDL_GL_SwapBuffers();
+ return 1;
+}
+
+
+int main(int argc, char *argv[])
+{
+ elf_firmware_t f;
+ const char * fname = "atmega48_charlcd.axf";
+ char path[256];
+ sprintf(path, "%s/%s", dirname(argv[0]), fname);
+ printf("Firmware pathname is %s\n", path);
+ elf_read_firmware(path, &f);
+
+ printf("firmware %s f=%d mmcu=%s\n", fname, (int)f.frequency, f.mmcu);
+
+ avr = avr_make_mcu_by_name(f.mmcu);
+ if (!avr) {
+ fprintf(stderr, "%s: AVR '%s' now known\n", argv[0], f.mmcu);
+ exit(1);
+ }
+
+ avr_init(avr);
+ avr_load_firmware(avr,&f);
+ ac_input_init(avr, &ac_input);
+ avr_connect_irq(
+ ac_input.irq + IRQ_AC_OUT,
+ avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('D'),2));
+
+ hd44780_init(avr, &hd44780);
+/* hd44780_print2x16(&hd44780); */
+
+ /* Connect Data Lines to Port B, 0-3 */
+ for( int i =0; i<4;i++){
+ avr_irq_register_notify(
+ avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), i),
+ hd44780_data_changed_hook,
+ &hd44780);
+ }
+ /* Connect Cmd Lines */
+ for( int i =4; i<7;i++){
+ avr_irq_register_notify(
+ avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), i),
+ hd44780_cmd_changed_hook,
+ &hd44780);
+ }
+
+ avr_vcd_init(avr, "gtkwave_output.vcd", &vcd_file, 100 /* usec */);
+ avr_vcd_add_signal(&vcd_file,
+ avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), IOPORT_IRQ_PIN_ALL), 8 /* bits */ ,
+ "portb" );
+
+ avr_vcd_add_signal(&vcd_file,
+ ac_input.irq + IRQ_AC_OUT, 1, "ac_input");
+
+ avr_vcd_start(&vcd_file);
+
+ //avr_gdb_init(avr);
+ //avr->state = cpu_Stopped;
+
+
+ avr_vcd_stop(&vcd_file);
+
+
+ if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
+ fprintf( stderr, "Video initialization failed: %s\n",SDL_GetError( ) );
+ Quit( 1 );
+ }
+ int done =0, isActive=1;
+ SDL_Event event;
+ int videoFlags = SDL_OPENGL | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE | SDL_RESIZABLE | SDL_HWSURFACE | SDL_HWACCEL;
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+ surface = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, videoFlags );
+ SDL_WM_SetCaption("HD44780 Simulation","");
+ if( !surface ) {
+ fprintf( stderr, "Video mode set failed: %s\n", SDL_GetError( ) );
+ Quit( 1 );
+ }
+ initGL( );
+ resizeWindow( SCREEN_WIDTH, SCREEN_HEIGHT);
+
+ pthread_t run;
+ pthread_create(&run, NULL, avr_run_thread, NULL);
+
+ while(!done){
+ while ( SDL_PollEvent( &event ) )
+ {
+ switch( event.type )
+ {
+ case SDL_ACTIVEEVENT:
+ if ( event.active.gain == 0 )
+ isActive = 0;
+ else
+ isActive = 1;
+ break;
+ case SDL_VIDEORESIZE:
+ /* handle resize event */
+ surface = SDL_SetVideoMode( event.resize.w,
+ event.resize.h,
+ 16, videoFlags );
+ if ( !surface )
+ {
+ fprintf( stderr, "Could not get a surface after resize: %s\n", SDL_GetError( ) );
+ Quit( 1 );
+ }
+ resizeWindow( event.resize.w, event.resize.h );
+ break;
+ case SDL_KEYDOWN:
+ /* handle key presses */
+ handleKeyPress( &event.key.keysym );
+ break;
+ case SDL_QUIT:
+ /* handle quit requests */
+ done = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ drawGLScene();
+ }
+ return 0;
+
+}
--- /dev/null
+import Image,struct
+img = Image.open('blu.tiff')
+
+class CharData(object):
+ def __init__(self, data):
+ if data is None:
+ self.data = [ [] for y in range(7) ]
+ else:
+ self.data = data
+
+ def concat( self, other ):
+ for y in range(7):
+ self.data[y] += other.data[y]
+
+ def get_bindata(self):
+ ll = len(self.data[0])
+ ret=''
+ for y in reversed(range(7)):
+ for x in self.data[y]:
+ ret += struct.pack('BBBB',*x)
+ return ret
+
+
+ def save_as(self, name):
+ height = 7
+ width = len(self.data[0])
+ outimg = Image.frombuffer( "RGBA", (width, height),
+ self.get_bindata())
+ outimg.save(name)
+
+
+def char_at(char_x,char_y):
+ """
+ char_x specifies, zero based, the x position of the character
+ """
+ start_x = 1+char_x+ 14*char_x+2
+ start_y = 1+char_y*22+1
+ print "Starting at %i,%i" %( start_x,start_y)
+ return CharData([[ img.getpixel( (start_x+2*x,start_y+2*y) ) for x in range(5)] for y in range(7)])
+
+
+chardata = CharData(None)
+for x in range(16): #0x00 - 0x0F
+ chardata.concat( char_at(0,x) )
+for x in range(16): #0x10 - 0x1F
+ chardata.concat( char_at(0,x) )
+for x in range(16): #0x20 - 0x2F
+ chardata.concat( char_at(1,x) )
+for x in range(16): #0x30 - 0x3F
+ chardata.concat( char_at(2,x) )
+for x in range(16): #0x40 - 0x4F
+ chardata.concat( char_at(3,x) )
+for x in range(16): #0x50 - 0x5F
+ chardata.concat( char_at(4,x) )
+for x in range(16): #0x60 - 0x6F
+ chardata.concat( char_at(5,x) )
+for x in range(16): #0x70 - 0x7F
+ chardata.concat( char_at(6,x) )
+for x in range(16): #0x80 - 0x8F
+ chardata.concat( char_at(0,x) )
+for x in range(16): #0x90 - 0x9F
+ chardata.concat( char_at(0,x) )
+for x in range(16): #0xA0 - 0xAF
+ chardata.concat( char_at(7,x) )
+for x in range(16): #0xB0 - 0xBF
+ chardata.concat( char_at(8,x) )
+for x in range(16): #0xC0 - 0xCF
+ chardata.concat( char_at(9,x) )
+for x in range(16): #0xD0 - 0xDF
+ chardata.concat( char_at(10,x) )
+for x in range(16): #0xE0 - 0xEF
+ chardata.concat( char_at(11,x) )
+for x in range(16): #0xF0 - 0xFF
+ chardata.concat( char_at(12,x) )
+print chardata.save_as('7x5font.tiff')
--- /dev/null
+#include "hd44780.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+void debug_print( const char* format, ... ) {
+
+ va_list args;
+ va_start( args, format );
+ #ifdef HD44780_DEBUG
+ vprintf( format, args );
+ #endif
+ va_end( args );
+}
+
+int check_flag( hd44780_t *b, int flag){
+ return (b->flags>>flag)&1;
+}
+
+void reset_cursor( hd44780_t *b){
+ b->cursor = b->ddram;
+}
+
+void clear_screen( hd44780_t *b){
+ memset(b->ddram,' ',80);
+}
+
+void handle_function_8bit( hd44780_t *b, int realportstate ){
+ debug_print("handle_function_8bit realportstate 0x%x\n",realportstate);
+ /*
+ if( realportstate == 0x22){
+ debug_print("Activating 4Bit Mode\n");
+ b->mode_4bit = 1;
+ }
+ */
+ if( realportstate == 1) {
+ clear_screen(b);
+ debug_print("Clear Screen\n");
+ }
+ if( realportstate >> 1 == 1) {
+ debug_print("Move Cursor to startpos\n");
+ reset_cursor(b);
+ }
+ if( realportstate >> 2 == 1) {
+ debug_print("Setting I/S mode\n");
+ b->flags &= ~(3<<HD44780_FLAG_S); //Clear S, I/D bits
+ b->flags |= (realportstate & 3)<<HD44780_FLAG_S;
+ }
+ if( realportstate >> 3 == 1) {
+ debug_print("Setting Display/Cursor Mode\n");
+ b->flags &= ~(7<<HD44780_FLAG_B); //Clear B,C,D bits
+ b->flags |= realportstate&7 << HD44780_FLAG_B; // Set B,C,D bits
+ }
+ if( realportstate >> 4 == 1) {
+ debug_print("Moving Display/Cursor Mode\n");
+ b->flags &= ~(3<<HD44780_FLAG_R_L); //Clear R/L,S/C
+ b->flags |= (realportstate & 3)<<HD44780_FLAG_R_L;
+ }
+ if( realportstate >> 5 == 1) {
+ debug_print("Functions\n");
+ b->flags &= ~(7<<HD44780_FLAG_F); //Clear F,N,DL bits
+ b->flags |= (realportstate>>2)&7 << HD44780_FLAG_F; // Set F,N,DL bits
+ if( !check_flag(b, HD44780_FLAG_D_L) ){
+ debug_print("Enabling 4Bit Mode\n");
+ b->mode_4bit = 1;
+ }
+ }
+ if( realportstate >> 6 == 1) printf("Set CGRAM Address\n");
+ if( realportstate >> 7 == 1) {
+ debug_print("Set DDRAM Address\n");
+ b->cursor = b->ddram + (realportstate & 0x7f);
+ }
+ debug_print("Flags are 0x%x\n",b->flags);
+}
+
+void handle_data_8bit( hd44780_t *b, int realportstate ){
+ /* printf("handle_data_8bit realportstate 0x%x\n",realportstate); */
+ *(b->cursor) = realportstate & 0xff;
+ if( !check_flag(b, HD44780_FLAG_S_C) ){
+ // Move Cursor
+ if( check_flag(b, HD44780_FLAG_I_D) ){
+ b->cursor++;
+ }
+ else{
+ b->cursor--;
+ }
+ }
+ else {
+ printf("!! NOT IMPLEMENTED\n");
+ // Move Display
+ if( check_flag(b, HD44780_FLAG_R_L) ){
+ //Move right
+
+ }
+ else {
+ // Move left
+ }
+ }
+ if( b->cursor < b->ddram || b->cursor > b->ddram+80){
+ debug_print("Cursor out of range!\n");
+ reset_cursor(b);
+ }
+ #ifdef HD44780_DEBUG
+ hd44780_print2x16( b );
+ #endif
+}
+
+void hd44780_init( struct avr_t *avr, struct hd44780_t * b) {
+ b->irq = avr_alloc_irq(0,IRQ_HD44780_COUNT);
+ b->portstate = 0x00;
+ b->mode_4bit = 0;
+ b->four_bit_cache = 0;
+ b->inits_recv = 0;
+ b->flags = 0;
+ reset_cursor(b);
+ clear_screen(b);
+}
+
+void hd44780_print2x16( struct hd44780_t *b){
+ printf("/******************\\\n| ");
+ fwrite( b->ddram, 1, 16, stdout);
+ printf(" |\n| ");
+// fputc('\n',stdout);
+ fwrite( b->ddram + 0x40, 1, 16, stdout);
+ printf(" |\n\\******************/\n");
+}
+
+void hd44780_data_changed_hook( struct avr_irq_t * irq, uint32_t value, void *param){
+ hd44780_t *b = (hd44780_t *)param;
+ int datapos = -1;
+ if( irq->irq == DATA_PIN_0) datapos = 0;
+ if( irq->irq == DATA_PIN_1) datapos = 1;
+ if( irq->irq == DATA_PIN_2) datapos = 2;
+ if( irq->irq == DATA_PIN_3) datapos = 3;
+ if( irq->irq == DATA_PIN_4) datapos = 4;
+ if( irq->irq == DATA_PIN_5) datapos = 5;
+ if( irq->irq == DATA_PIN_6) datapos = 6;
+ if( irq->irq == DATA_PIN_7) datapos = 7;
+ if( datapos >= 0){
+ if( value == 1) b->portstate |= 1<<datapos;
+ else b->portstate &= ~(1<<datapos);
+ }
+}
+
+
+void hd44780_cmd_changed_hook( struct avr_irq_t * irq, uint32_t value, void *param){
+ hd44780_t *b = (hd44780_t *)param;
+ if( irq->irq == RS_PIN){
+ b->rs=value;
+ }
+ if( irq->irq == RW_PIN){
+ b->rw=value;
+ }
+ if( irq->irq == ENABLE_PIN && value == 0){
+ debug_print("enable pulse! portstate 0x%x\n", b->portstate);
+ if( b->inits_recv < 3 ){
+ if( b->portstate == 0x30 ){
+ debug_print("Init received\n");
+ b->inits_recv++;
+ }
+ else debug_print("Uuups, received command before fully initialized?\n");
+ }
+ else {
+ int realportstate=0;
+ int received = 1;
+ if( b->mode_4bit == 1) b->four_bit_cache = b->portstate, b->mode_4bit++,received=0;
+ else if( b->mode_4bit == 2) {
+ realportstate = (b->four_bit_cache&0xf0) | (b->portstate&0xf0)>>4;
+ b->mode_4bit=1;
+ }
+ else realportstate = b->portstate;
+ debug_print("four bit cache is 0x%x\n",b->four_bit_cache);
+
+ if(received){
+ if( !b->rs ) handle_function_8bit( b, realportstate );
+ else handle_data_8bit( b, realportstate );
+ }
+ }
+ }
+// printf("pin %i is now %i, portstate 0x%x\n", irq->irq, value, b->portstate);
+}
+
+
+
--- /dev/null
+#ifndef __HD44780_H__
+#define __HD44780_H__
+
+#include "sim_irq.h"
+
+/******************
+ * Simulates a HD44780 controlled character LED.
+ * All the Data Pins have to be on the same Port.
+ * All the Cmd Pins have to be on the same Port. In 4 Bit mode,
+ * they can share one Port.
+ * For output of the display contents, use hd44780_print2x16 or a opengl function.
+ ******************/
+
+#define ENABLE_PIN 5
+#define RW_PIN 6
+#define RS_PIN 4
+/* Use -1 for not connected */
+#define DATA_PIN_0 -1
+#define DATA_PIN_1 -1
+#define DATA_PIN_2 -1
+#define DATA_PIN_3 -1
+#define DATA_PIN_4 0
+#define DATA_PIN_5 1
+#define DATA_PIN_6 2
+#define DATA_PIN_7 3
+
+/* #define HD44780_DEBUG */
+
+enum {
+ HD44780_FLAG_F = 0, //5x7 Font, 5x10 Font
+ HD44780_FLAG_N, //1-zeiliges Display, 2/4-zeiliges Display
+ HD44780_FLAG_D_L, //4-Bit Interface, 8-Bit Interface
+ HD44780_FLAG_R_L, // Nach links schieben,Nach rechts schieben
+ HD44780_FLAG_S_C, //Cursor bewegen, Displayinhalt schieben
+ HD44780_FLAG_B, //Cursor blinkt nicht, Cursor blinkt
+ HD44780_FLAG_C, //Cursor aus,Cursor an
+ HD44780_FLAG_D, //Display aus,Display an
+ HD44780_FLAG_S, //Displayinhalt fest, Displayinhalt weiterschieben
+ HD44780_FLAG_I_D
+};
+
+enum {
+ IRQ_HD44780_IN = 0,
+ IRQ_HD44780_COUNT
+};
+
+
+typedef struct hd44780_t {
+ avr_irq_t * irq;
+ struct avr_t * avr;
+ char *cursor;
+ char ddram[80];
+ char cgram[64];
+ uint32_t rw; /* R/W pin */
+ uint32_t rs; /* RS pin */
+ int portstate;
+ char mode_4bit; /* 0=disabled, 1=waitingforfirstnibble, 2=waitingforsecondnibble */
+ uint32_t flags;
+ int four_bit_cache;
+ char inits_recv; /* num of init sequences received */
+} hd44780_t;
+
+void hd44780_init( struct avr_t *avr, struct hd44780_t * b);
+void hd44780_print2x16( struct hd44780_t *b);
+
+void hd44780_data_changed_hook( struct avr_irq_t * irq, uint32_t value, void *param);
+void hd44780_cmd_changed_hook( struct avr_irq_t * irq, uint32_t value, void *param);
+
+#endif
--- /dev/null
+#include "hd44780_glut.h"
+
+#include "SDL.h"
+#include "SDL_image.h"
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+static GLuint font_texture;
+static int charwidth = 5;
+static int charheight = 7;
+
+void hd44780_gl_init(){
+ SDL_Surface *image;
+ image = IMG_Load("font.tiff");
+ if( !image) {
+ printf("Problem loading texture\n");
+ return;
+ }
+ glGenTextures(1,&font_texture);
+ glBindTexture(GL_TEXTURE_2D, font_texture);
+/* printf("imagew %i, imageh %i, bytesperpixel %i\n", image->w, image->h, image->format->BytesPerPixel); */
+ glTexImage2D( GL_TEXTURE_2D, 0, 4, image->w, image->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glScalef( 1.0f/(GLfloat)image->w, 1.0f/(GLfloat)image->h,1.0f);
+
+ SDL_FreeSurface(image);
+ glMatrixMode(GL_MODELVIEW);
+}
+
+void glputchar(char c){
+ int index = c;
+ int left = index * charwidth;
+ int right = index*charwidth+charwidth;
+ int top = 0;
+ int bottom =7;
+
+ glDisable(GL_TEXTURE_2D);
+ glColor3f( 0.0f, 1.0f, 0.0f);
+ glBegin( GL_QUADS);
+ glVertex3i( 5, 7, 0 );
+ glVertex3i( 0, 7, 0 );
+ glVertex3i( 0, 0, 0 );
+ glVertex3i( 5, 0, 0 );
+ glEnd( );
+
+ glEnable(GL_TEXTURE_2D);
+ glColor3f( 1.0f, 1.0f, 1.0f);
+ glBindTexture(GL_TEXTURE_2D, font_texture);
+ glBegin( GL_QUADS);
+ glTexCoord2i(right,top); glVertex3i( 5, 7, 0 );
+ glTexCoord2i(left, top); glVertex3i( 0, 7, 0 );
+ glTexCoord2i(left, bottom); glVertex3i( 0, 0, 0 );
+ glTexCoord2i(right,bottom); glVertex3i( 5, 0, 0 );
+ glEnd( );
+
+}
+
+void glputstr( char *str){
+ while( *(++str) != 0 ){
+ glputchar(*str);
+ glTranslatef(6,0,0);
+ }
+}
+
+void hd44780_gl_draw( hd44780_t *b){
+ int rows = 16;
+ int lines = 2;
+ int border = 3;
+ glDisable(GL_TEXTURE_2D);
+ glColor3f(0.0f,0.4f,0.0f);
+ glTranslatef(0,-8,0);
+ glBegin(GL_QUADS);
+ glVertex3f( rows*charwidth + (rows-1) + border, -border,0);
+ glVertex3f( - border, -border,0);
+ glVertex3f( - border, lines*charheight + (lines-1)+border,0);
+ glVertex3f( rows*charwidth + (rows-1) + border, lines*charheight + (lines-1)+border,0);
+ glEnd();
+ glTranslatef(0,8,0);
+ glColor3f(1.0f,1.0f,1.0f);
+ for( int i=0; i<16; i++) {
+ glputchar( b->ddram[i] );
+ glTranslatef(6,0,0);
+ }
+ glTranslatef(-96,-8,0);
+ for( int i=0; i<16; i++) {
+ glputchar( b->ddram[i+0x40] );
+ glTranslatef(6,0,0);
+ }
+
+}
--- /dev/null
+#ifndef __HD44780_GLUT_H__
+#define __HD44780_GLUT_H__
+
+#include "hd44780.h"
+
+void hd44780_gl_draw( hd44780_t *b);
+
+void hd44780_gl_init();
+
+#endif