Commit 74f174c6a1339e88b85a14da3f832e38ddb1d75b
authorluki <luki@localhost.(none)>
Sat, 23 Jan 2010 15:25:47 +0000 (16:25 +0100)
committerluki <luki@localhost.(none)>
Sat, 23 Jan 2010 15:25:47 +0000 (16:25 +0100)
14 files changed:
examples/board_charlcd/Makefile [new file with mode: 0644]
examples/board_charlcd/ac_input.c [new file with mode: 0644]
examples/board_charlcd/ac_input.h [new file with mode: 0644]
examples/board_charlcd/atmega48_charlcd.c [new file with mode: 0644]
examples/board_charlcd/atmega48_lcd.c [new file with mode: 0644]
examples/board_charlcd/atmega48_lcd.h [new file with mode: 0644]
examples/board_charlcd/charlcd.c [new file with mode: 0644]
examples/board_charlcd/data/blu.tiff [new file with mode: 0644]
examples/board_charlcd/data/processblu.py [new file with mode: 0644]
examples/board_charlcd/font.tiff [new file with mode: 0644]
examples/board_charlcd/hd44780.c [new file with mode: 0644]
examples/board_charlcd/hd44780.h [new file with mode: 0644]
examples/board_charlcd/hd44780_glut.c [new file with mode: 0644]
examples/board_charlcd/hd44780_glut.h [new file with mode: 0644]

diff --git a/examples/board_charlcd/Makefile b/examples/board_charlcd/Makefile
new file mode 100644 (file)
index 0000000..8da9583
--- /dev/null
@@ -0,0 +1,70 @@
+# 
+#      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
diff --git a/examples/board_charlcd/ac_input.c b/examples/board_charlcd/ac_input.c
new file mode 100644 (file)
index 0000000..29447f5
--- /dev/null
@@ -0,0 +1,18 @@
+
+#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);
+}
diff --git a/examples/board_charlcd/ac_input.h b/examples/board_charlcd/ac_input.h
new file mode 100644 (file)
index 0000000..07c2c4b
--- /dev/null
@@ -0,0 +1,23 @@
+#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
diff --git a/examples/board_charlcd/atmega48_charlcd.c b/examples/board_charlcd/atmega48_charlcd.c
new file mode 100644 (file)
index 0000000..993190a
--- /dev/null
@@ -0,0 +1,62 @@
+#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);
+    }
+
+}
diff --git a/examples/board_charlcd/atmega48_lcd.c b/examples/board_charlcd/atmega48_lcd.c
new file mode 100644 (file)
index 0000000..9822188
--- /dev/null
@@ -0,0 +1,146 @@
+// 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
diff --git a/examples/board_charlcd/atmega48_lcd.h b/examples/board_charlcd/atmega48_lcd.h
new file mode 100644 (file)
index 0000000..ebb6909
--- /dev/null
@@ -0,0 +1,33 @@
+#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
diff --git a/examples/board_charlcd/charlcd.c b/examples/board_charlcd/charlcd.c
new file mode 100644 (file)
index 0000000..3692754
--- /dev/null
@@ -0,0 +1,228 @@
+#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;
+
+}
diff --git a/examples/board_charlcd/data/blu.tiff b/examples/board_charlcd/data/blu.tiff
new file mode 100644 (file)
index 0000000..0db74e2
Binary files /dev/null and b/examples/board_charlcd/data/blu.tiff differ
diff --git a/examples/board_charlcd/data/processblu.py b/examples/board_charlcd/data/processblu.py
new file mode 100644 (file)
index 0000000..17f89f6
--- /dev/null
@@ -0,0 +1,75 @@
+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')
diff --git a/examples/board_charlcd/font.tiff b/examples/board_charlcd/font.tiff
new file mode 100644 (file)
index 0000000..d5a146e
Binary files /dev/null and b/examples/board_charlcd/font.tiff differ
diff --git a/examples/board_charlcd/hd44780.c b/examples/board_charlcd/hd44780.c
new file mode 100644 (file)
index 0000000..46178e8
--- /dev/null
@@ -0,0 +1,185 @@
+#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);
+}
+
+
+
diff --git a/examples/board_charlcd/hd44780.h b/examples/board_charlcd/hd44780.h
new file mode 100644 (file)
index 0000000..4b4ce12
--- /dev/null
@@ -0,0 +1,69 @@
+#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 
diff --git a/examples/board_charlcd/hd44780_glut.c b/examples/board_charlcd/hd44780_glut.c
new file mode 100644 (file)
index 0000000..4f9dee8
--- /dev/null
@@ -0,0 +1,94 @@
+#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);
+    }
+    
+}
diff --git a/examples/board_charlcd/hd44780_glut.h b/examples/board_charlcd/hd44780_glut.h
new file mode 100644 (file)
index 0000000..53d9403
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __HD44780_GLUT_H__
+#define __HD44780_GLUT_H__
+
+#include "hd44780.h"
+
+void hd44780_gl_draw( hd44780_t *b);
+
+void hd44780_gl_init();
+
+#endif