New example board: reprap
[simavr] / examples / board_reprap / reprap.c
1 /*
2         simduino.c
3
4         Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
5
6         This file is part of simavr.
7
8         simavr is free software: you can redistribute it and/or modify
9         it under the terms of the GNU General Public License as published by
10         the Free Software Foundation, either version 3 of the License, or
11         (at your option) any later version.
12
13         simavr is distributed in the hope that it will be useful,
14         but WITHOUT ANY WARRANTY; without even the implied warranty of
15         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16         GNU General Public License for more details.
17
18         You should have received a copy of the GNU General Public License
19         along with simavr.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <unistd.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <libgen.h>
29
30 #if __APPLE__
31 #include <GLUT/glut.h>
32 #else
33 #include <GL/glut.h>
34 #endif
35 #include <pthread.h>
36
37 #include "sim_avr.h"
38 #include "avr_ioport.h"
39 #include "sim_elf.h"
40 #include "sim_hex.h"
41 #include "sim_gdb.h"
42 #include "sim_vcd_file.h"
43
44 #include "button.h"
45 #include "thermistor.h"
46 #include "uart_pty.h"
47
48 #define __AVR_ATmega644__
49 #include "marlin/pins.h"
50
51 #define PROGMEM
52 #define THERMISTORHEATER_0 5
53 #include "marlin/thermistortables.h"
54
55 thermistor_t    therm_hotend;
56 thermistor_t    therm_hotbed;
57 button_t button;
58 uart_pty_t uart_pty;
59 int do_button_press = 0;
60 avr_t * avr = NULL;
61 avr_vcd_t vcd_file;
62 uint8_t pin_state = 0;  // current port B
63
64 float pixsize = 64;
65 int window;
66
67 /*
68  * called when the AVR change any of the pins on port B
69  * so lets update our buffer
70  */
71 void pin_changed_hook(struct avr_irq_t * irq, uint32_t value, void * param)
72 {
73 //      pin_state = (pin_state & ~(1 << irq->irq)) | (value << irq->irq);
74 }
75
76 void displayCB(void)            /* function called whenever redisplay needed */
77 {
78         // OpenGL rendering goes here...
79         glClear(GL_COLOR_BUFFER_BIT);
80
81         // Set up modelview matrix
82         glMatrixMode(GL_MODELVIEW); // Select modelview matrix
83         glLoadIdentity(); // Start with an identity matrix
84
85         //float grid = pixsize;
86         //float size = grid * 0.8;
87     glBegin(GL_QUADS);
88         glColor3f(1,0,0);
89
90 #if 0
91         for (int di = 0; di < 8; di++) {
92                 char on = (pin_state & (1 << di)) != 0;
93                 if (on) {
94                         float x = (di) * grid;
95                         float y = 0; //(si * grid * 8) + (di * grid);
96                         glVertex2f(x + size, y + size);
97                         glVertex2f(x, y + size);
98                         glVertex2f(x, y);
99                         glVertex2f(x + size, y);
100                 }
101         }
102 #endif
103     glEnd();
104     glutSwapBuffers();
105     //glFlush();                                /* Complete any pending operations */
106 }
107
108 void keyCB(unsigned char key, int x, int y)     /* called on key press */
109 {
110         if (key == 'q')
111                 exit(0);
112         //static uint8_t buf[64];
113         switch (key) {
114                 case 'q':
115                 case 0x1f: // escape
116                         exit(0);
117                         break;
118                 case ' ':
119                         do_button_press++; // pass the message to the AVR thread
120                         break;
121                 case 'r':
122                         printf("Starting VCD trace\n");
123                         avr_vcd_start(&vcd_file);
124                         break;
125                 case 's':
126                         printf("Stopping VCD trace\n");
127                         avr_vcd_stop(&vcd_file);
128                         break;
129         }
130 }
131
132 // gl timer. if the pin have changed states, refresh display
133 void timerCB(int i)
134 {
135         //static uint8_t oldstate = 0xff;
136         // restart timer
137         glutTimerFunc(1000/64, timerCB, 0);
138 #if 0
139         if (oldstate != pin_state) {
140                 oldstate = pin_state;
141                 glutPostRedisplay();
142         }
143 #endif
144 }
145
146 static void * avr_run_thread(void * oaram)
147 {
148 //      int b_press = do_button_press;
149
150         while (1) {
151                 int state = avr_run(avr);
152                 if ( state == cpu_Done || state == cpu_Crashed)
153                         break;
154         }
155         return NULL;
156 }
157
158
159 char avr_flash_path[1024];
160 int avr_flash_fd = 0;
161
162 // avr special flash initalization
163 // here: open and map a file to enable a persistent storage for the flash memory
164 void avr_special_init( avr_t * avr)
165 {
166         // open the file
167         avr_flash_fd = open(avr_flash_path, O_RDWR|O_CREAT, 0644);
168         if (avr_flash_fd < 0) {
169                 perror(avr_flash_path);
170                 exit(1);
171         }
172         // resize and map the file the file
173         (void)ftruncate(avr_flash_fd, avr->flashend + 1);
174         ssize_t r = read(avr_flash_fd, avr->flash, avr->flashend + 1);
175         if (r != avr->flashend + 1) {
176                 fprintf(stderr, "unable to load flash memory\n");
177                 perror(avr_flash_path);
178                 exit(1);
179         }
180 }
181
182 // avr special flash deinitalization
183 // here: cleanup the persistent storage
184 void avr_special_deinit( avr_t* avr)
185 {
186         puts(__func__);
187         lseek(avr_flash_fd, SEEK_SET, 0);
188         ssize_t r = write(avr_flash_fd, avr->flash, avr->flashend + 1);
189         if (r != avr->flashend + 1) {
190                 fprintf(stderr, "unable to load flash memory\n");
191                 perror(avr_flash_path);
192         }
193         close(avr_flash_fd);
194         uart_pty_stop(&uart_pty);
195 }
196
197 int main(int argc, char *argv[])
198 {
199         int debug = 0;
200
201         for (int i = 1; i < argc; i++)
202                 if (!strcmp(argv[i], "-d"))
203                         debug++;
204         avr = avr_make_mcu_by_name("atmega644");
205         if (!avr) {
206                 fprintf(stderr, "%s: Error creating the AVR core\n", argv[0]);
207                 exit(1);
208         }
209 //      snprintf(avr_flash_path, sizeof(avr_flash_path), "%s/%s", pwd, "simduino_flash.bin");
210         strcpy(avr_flash_path,  "reprap_flash.bin");
211         // register our own functions
212         avr->special_init = avr_special_init;
213         avr->special_deinit = avr_special_deinit;
214         avr_init(avr);
215         avr->frequency = 20000000;
216         avr->aref = avr->avcc = avr->vcc = 5 * 1000;    // needed for ADC
217
218         if (1) {
219                 elf_firmware_t f;
220                 const char * fname = "/opt/reprap/tvrrug/Marlin.base/Marlin/applet/Marlin.elf";
221                 elf_read_firmware(fname, &f);
222
223                 printf("firmware %s f=%d mmcu=%s\n", fname, (int)f.frequency, f.mmcu);
224                 avr_load_firmware(avr, &f);
225         } else {
226                 char path[1024];
227                 uint32_t base, size;
228 //              snprintf(path, sizeof(path), "%s/%s", pwd, "ATmegaBOOT_168_atmega328.ihex");
229                 strcpy(path, "marlin/Marlin.hex");
230                 //strcpy(path, "marlin/bootloader-644-20MHz.hex");
231                 uint8_t * boot = read_ihex_file(path, &size, &base);
232                 if (!boot) {
233                         fprintf(stderr, "%s: Unable to load %s\n", argv[0], path);
234                         exit(1);
235                 }
236                 printf("Firmware %04x: %d\n", base, size);
237                 memcpy(avr->flash + base, boot, size);
238                 free(boot);
239                 avr->pc = base;
240                 avr->codeend = avr->flashend;
241         }
242         //avr->trace = 1;
243
244         // even if not setup at startup, activate gdb if crashing
245         avr->gdb_port = 1234;
246         if (debug) {
247                 printf("AVR is stopped, waiting on gdb on port %d. Use 'target remote :%d' in avr-gdb\n",
248                                 avr->gdb_port, avr->gdb_port);
249                 avr->state = cpu_Stopped;
250                 avr_gdb_init(avr);
251         }
252
253         uart_pty_init(avr, &uart_pty);
254         uart_pty_connect(&uart_pty, '0');
255
256         thermistor_init(avr, &therm_hotend, TEMP_0_PIN,
257                         (short*)temptable_5, sizeof(temptable_5) / sizeof(short) / 2, OVERSAMPLENR, 22.5f);
258         thermistor_init(avr, &therm_hotbed, TEMP_BED_PIN,
259                         (short*)temptable_5, sizeof(temptable_5) / sizeof(short) / 2, OVERSAMPLENR, 22.0f);
260
261         /*
262          * OpenGL init, can be ignored
263          */
264         glutInit(&argc, argv);          /* initialize GLUT system */
265
266         glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
267         glutInitWindowSize(8 * pixsize, 1 * pixsize);           /* width=400pixels height=500pixels */
268         window = glutCreateWindow("Glut");      /* create window */
269
270         // Set up projection matrix
271         glMatrixMode(GL_PROJECTION); // Select projection matrix
272         glLoadIdentity(); // Start with an identity matrix
273         glOrtho(0, 8 * pixsize, 0, 1 * pixsize, 0, 10);
274         glScalef(1,-1,1);
275         glTranslatef(0, -1 * pixsize, 0);
276
277         glutDisplayFunc(displayCB);             /* set window's display callback */
278         glutKeyboardFunc(keyCB);                /* set window's key callback */
279         glutTimerFunc(1000 / 24, timerCB, 0);
280
281         // the AVR run on it's own thread. it even allows for debugging!
282         pthread_t run;
283         pthread_create(&run, NULL, avr_run_thread, NULL);
284
285         glutMainLoop();
286 }