make uart_pty threadsafe
[simavr] / examples / board_hd77480 / charlcd.c
1 /*
2         charlcd.c
3
4         Copyright Luki <humbell@ethz.ch>
5         Copyright 2011 Michel Pollet <buserror@gmail.com>
6
7         This file is part of simavr.
8
9         simavr is free software: you can redistribute it and/or modify
10         it under the terms of the GNU General Public License as published by
11         the Free Software Foundation, either version 3 of the License, or
12         (at your option) any later version.
13
14         simavr is distributed in the hope that it will be useful,
15         but WITHOUT ANY WARRANTY; without even the implied warranty of
16         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17         GNU General Public License for more details.
18
19         You should have received a copy of the GNU General Public License
20         along with simavr.  If not, see <http://www.gnu.org/licenses/>.
21  */
22
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <libgen.h>
26
27 #include "sim_avr.h"
28 #include "avr_ioport.h"
29 #include "sim_elf.h"
30 #include "sim_gdb.h"
31 #include "sim_vcd_file.h"
32
33 #if __APPLE__
34 #include <GLUT/glut.h>
35 #else
36 #include <GL/glut.h>
37 #endif
38 #include <pthread.h>
39
40 #include "ac_input.h"
41 #include "hd44780_glut.h"
42
43
44 //float pixsize = 16;
45 int window;
46
47 avr_t * avr = NULL;
48 avr_vcd_t vcd_file;
49 ac_input_t ac_input;
50 hd44780_t hd44780;
51
52 int color = 0;
53 uint32_t colors[][4] = {
54                 { 0x00aa00ff, 0x00cc00ff, 0x000000ff, 0x00000055 },     // fluo green
55                 { 0xaa0000ff, 0xcc0000ff, 0x000000ff, 0x00000055 },     // red
56 };
57
58 static void *
59 avr_run_thread(
60                 void * ignore)
61 {
62         while (1) {
63                 avr_run(avr);
64         }
65         return NULL;
66 }
67
68 void keyCB(
69                 unsigned char key, int x, int y)        /* called on key press */
70 {
71         switch (key) {
72                 case 'q':
73                         avr_vcd_stop(&vcd_file);
74                         exit(0);
75                         break;
76                 case 'r':
77                         printf("Starting VCD trace; press 's' to stop\n");
78                         avr_vcd_start(&vcd_file);
79                         break;
80                 case 's':
81                         printf("Stopping VCD trace\n");
82                         avr_vcd_stop(&vcd_file);
83                         break;
84         }
85 }
86
87
88 void displayCB(void)            /* function called whenever redisplay needed */
89 {
90         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
91         glMatrixMode(GL_MODELVIEW); // Select modelview matrix
92         glPushMatrix();
93         glLoadIdentity(); // Start with an identity matrix
94         glScalef(3, 3, 1);
95
96         hd44780_gl_draw(
97                 &hd44780,
98                         colors[color][0], /* background */
99                         colors[color][1], /* character background */
100                         colors[color][2], /* text */
101                         colors[color][3] /* shadow */ );
102         glPopMatrix();
103     glutSwapBuffers();
104 }
105
106 // gl timer. if the lcd is dirty, refresh display
107 void timerCB(int i)
108 {
109         //static int oldstate = -1;
110         // restart timer
111         glutTimerFunc(1000/64, timerCB, 0);
112         glutPostRedisplay();
113 }
114
115 int
116 initGL(int w, int h)
117 {
118         // Set up projection matrix
119         glMatrixMode(GL_PROJECTION); // Select projection matrix
120         glLoadIdentity(); // Start with an identity matrix
121         glOrtho(0, w, 0, h, 0, 10);
122         glScalef(1,-1,1);
123         glTranslatef(0, -1 * h, 0);
124
125         glutDisplayFunc(displayCB);             /* set window's display callback */
126         glutKeyboardFunc(keyCB);                /* set window's key callback */
127         glutTimerFunc(1000 / 24, timerCB, 0);
128
129         glEnable(GL_TEXTURE_2D);
130         glShadeModel(GL_SMOOTH);
131
132         glClearColor(0.8f, 0.8f, 0.8f, 1.0f);
133         glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
134
135         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
136         glEnable(GL_BLEND);
137
138         hd44780_gl_init();
139
140         return 1;
141 }
142
143 int
144 main(
145                 int argc,
146                 char *argv[])
147 {
148         elf_firmware_t f;
149         const char * fname = "atmega48_charlcd.axf";
150 //      char path[256];
151 //      sprintf(path, "%s/%s", dirname(argv[0]), fname);
152 //      printf("Firmware pathname is %s\n", path);
153         elf_read_firmware(fname, &f);
154
155         printf("firmware %s f=%d mmcu=%s\n", fname, (int) f.frequency, f.mmcu);
156
157         avr = avr_make_mcu_by_name(f.mmcu);
158         if (!avr) {
159                 fprintf(stderr, "%s: AVR '%s' not known\n", argv[0], f.mmcu);
160                 exit(1);
161         }
162
163         avr_init(avr);
164         avr_load_firmware(avr, &f);
165         ac_input_init(avr, &ac_input);
166         avr_connect_irq(ac_input.irq + IRQ_AC_OUT, avr_io_getirq(avr,
167                 AVR_IOCTL_IOPORT_GETIRQ('D'), 2));
168
169         hd44780_init(avr, &hd44780, 20, 4);
170
171         /* Connect Data Lines to Port B, 0-3 */
172         /* These are bidirectional too */
173         for (int i = 0; i < 4; i++) {
174                 avr_irq_t * iavr = avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), i);
175                 avr_irq_t * ilcd = hd44780.irq + IRQ_HD44780_D4 + i;
176                 // AVR -> LCD
177                 avr_connect_irq(iavr, ilcd);
178                 // LCD -> AVR
179                 avr_connect_irq(ilcd, iavr);
180         }
181         avr_connect_irq(
182                         avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), 4),
183                         hd44780.irq + IRQ_HD44780_RS);
184         avr_connect_irq(
185                         avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), 5),
186                         hd44780.irq + IRQ_HD44780_E);
187         avr_connect_irq(
188                         avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), 6),
189                         hd44780.irq + IRQ_HD44780_RW);
190
191
192         avr_vcd_init(avr, "gtkwave_output.vcd", &vcd_file, 10 /* usec */);
193         avr_vcd_add_signal(&vcd_file,
194                         avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), IOPORT_IRQ_PIN_ALL),
195                         4 /* bits */, "D4-D7");
196         avr_vcd_add_signal(&vcd_file,
197                         avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), 4),
198                         1 /* bits */, "RS");
199         avr_vcd_add_signal(&vcd_file,
200                         avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), 5),
201                         1 /* bits */, "E");
202         avr_vcd_add_signal(&vcd_file,
203                         avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), 6),
204                         1 /* bits */, "RW");
205         avr_vcd_add_signal(&vcd_file,
206                         hd44780.irq + IRQ_HD44780_BUSY,
207                         1 /* bits */, "LCD_BUSY");
208         avr_vcd_add_signal(&vcd_file,
209                         hd44780.irq + IRQ_HD44780_ADDR,
210                         7 /* bits */, "LCD_ADDR");
211         avr_vcd_add_signal(&vcd_file,
212                         hd44780.irq + IRQ_HD44780_DATA_IN,
213                         8 /* bits */, "LCD_DATA_IN");
214         avr_vcd_add_signal(&vcd_file,
215                         hd44780.irq + IRQ_HD44780_DATA_OUT,
216                         8 /* bits */, "LCD_DATA_OUT");
217
218         avr_vcd_add_signal(&vcd_file, ac_input.irq + IRQ_AC_OUT, 1, "ac_input");
219
220         avr_vcd_start(&vcd_file);
221
222         printf( "Demo : This is HD44780 LCD demo\n"
223                         "   You can configure the width&height of the LCD in the code\n"
224                         "   Press 'r' to start recording a 'wave' file - with a LOT of data\n"
225                         "   Press 's' to stop recording\n"
226                         );
227
228         /*
229          * OpenGL init, can be ignored
230          */
231         glutInit(&argc, argv);          /* initialize GLUT system */
232
233         int w = 5 + hd44780.w * 6;
234         int h = 5 + hd44780.h * 8;
235         int pixsize = 3;
236
237         glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
238         glutInitWindowSize(w * pixsize, h * pixsize);           /* width=400pixels height=500pixels */
239         window = glutCreateWindow("Press 'q' to quit"); /* create window */
240
241         initGL(w * pixsize, h * pixsize);
242
243         pthread_t run;
244         pthread_create(&run, NULL, avr_run_thread, NULL);
245
246         glutMainLoop();
247 }