4 Copyright 2008, 2009 Michel Pollet <buserror@gmail.com>
6 This file is part of simavr.
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.
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.
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/>.
32 #include "avr_ioport.h"
37 #include "reprap_gl.h"
41 #include "arduidiot_pins.h"
43 #define __AVR_ATmega644__
44 #include "marlin/pins.h"
48 #include "marlin/Configuration.h"
51 * these are the sources of heat and cold to register to the heatpots
64 // gnu hackery to make sure the parameter is expanded
65 #define _TERMISTOR_TABLE(num) \
67 #define TERMISTOR_TABLE(num) \
71 * called when the AVR change any of the pins on port B
72 * so lets update our buffer
76 struct avr_irq_t * irq,
80 // printf("%s %d\n", __func__, value);
81 // pin_state = (pin_state & ~(1 << irq->irq)) | (value << irq->irq);
89 struct avr_irq_t * irq,
93 // printf("%s %d\n", __func__, value);
94 // pin_state = (pin_state & ~(1 << irq->irq)) | (value << irq->irq);
101 hotend_fan_change_hook(
102 struct avr_irq_t * irq,
106 printf("%s %d\n", __func__, value);
107 // pin_state = (pin_state & ~(1 << irq->irq)) | (value << irq->irq);
116 char avr_flash_path[1024];
117 int avr_flash_fd = 0;
119 // avr special flash initalization
120 // here: open and map a file to enable a persistent storage for the flash memory
121 void avr_special_init( avr_t * avr)
124 avr_flash_fd = open(avr_flash_path, O_RDWR|O_CREAT, 0644);
125 if (avr_flash_fd < 0) {
126 perror(avr_flash_path);
129 // resize and map the file the file
130 (void)ftruncate(avr_flash_fd, avr->flashend + 1);
131 ssize_t r = read(avr_flash_fd, avr->flash, avr->flashend + 1);
132 if (r != avr->flashend + 1) {
133 fprintf(stderr, "unable to load flash memory\n");
134 perror(avr_flash_path);
139 // avr special flash deinitalization
140 // here: cleanup the persistent storage
141 void avr_special_deinit( avr_t* avr)
144 lseek(avr_flash_fd, SEEK_SET, 0);
145 ssize_t r = write(avr_flash_fd, avr->flash, avr->flashend + 1);
146 if (r != avr->flashend + 1) {
147 fprintf(stderr, "unable to load flash memory\n");
148 perror(avr_flash_path);
151 uart_pty_stop(&reprap.uart_pty);
154 #define MEGA644_GPIOR0 0x3e
157 reprap_relief_callback(
163 // printf("%s write %x\n", __func__, addr);
164 static uint16_t tick = 0;
185 uart_pty_init(avr, &r->uart_pty);
186 uart_pty_connect(&r->uart_pty, '0');
188 thermistor_init(avr, &r->therm_hotend, 0,
189 (short*)TERMISTOR_TABLE(TEMP_SENSOR_0),
190 sizeof(TERMISTOR_TABLE(TEMP_SENSOR_0)) / sizeof(short) / 2,
191 OVERSAMPLENR, 25.0f);
192 thermistor_init(avr, &r->therm_hotbed, 2,
193 (short*)TERMISTOR_TABLE(TEMP_SENSOR_BED),
194 sizeof(TERMISTOR_TABLE(TEMP_SENSOR_BED)) / sizeof(short) / 2,
195 OVERSAMPLENR, 30.0f);
196 thermistor_init(avr, &r->therm_spare, 1,
197 (short*)temptable_5, sizeof(temptable_5) / sizeof(short) / 2,
198 OVERSAMPLENR, 10.0f);
200 heatpot_init(avr, &r->hotend, "hotend", 28.0f);
201 heatpot_init(avr, &r->hotbed, "hotbed", 25.0f);
203 heatpot_tally(&r->hotend, TALLY_AMBIANT, -0.5f);
204 heatpot_tally(&r->hotbed, TALLY_AMBIANT, -0.3f);
206 /* connect heatpot temp output to thermistors */
207 avr_connect_irq(r->hotend.irq + IRQ_HEATPOT_TEMP_OUT,
208 r->therm_hotend.irq + IRQ_TERM_TEMP_VALUE_IN);
209 avr_connect_irq(r->hotbed.irq + IRQ_HEATPOT_TEMP_OUT,
210 r->therm_hotbed.irq + IRQ_TERM_TEMP_VALUE_IN);
212 avr_irq_register_notify(
213 get_ardu_irq(avr, HEATER_0_PIN, arduidiot_644),
214 hotend_change_hook, NULL);
215 avr_irq_register_notify(
216 get_ardu_irq(avr, FAN_PIN, arduidiot_644),
217 hotend_fan_change_hook, NULL);
218 avr_irq_register_notify(
219 get_ardu_irq(avr, HEATER_BED_PIN, arduidiot_644),
220 hotbed_change_hook, NULL);
222 //avr_irq_register_notify()
223 float axis_pp_per_mm[4] = DEFAULT_AXIS_STEPS_PER_UNIT; // from Marlin!
225 avr_irq_t * e = get_ardu_irq(avr, X_ENABLE_PIN, arduidiot_644);
226 avr_irq_t * s = get_ardu_irq(avr, X_STEP_PIN, arduidiot_644);
227 avr_irq_t * d = get_ardu_irq(avr, X_DIR_PIN, arduidiot_644);
228 avr_irq_t * m = get_ardu_irq(avr, X_MIN_PIN, arduidiot_644);
230 stepper_init(avr, &r->step_x, "X", axis_pp_per_mm[0], 100, 200, 0);
231 stepper_connect(&r->step_x, s, d, e, m, stepper_endstop_inverted);
234 avr_irq_t * e = get_ardu_irq(avr, Y_ENABLE_PIN, arduidiot_644);
235 avr_irq_t * s = get_ardu_irq(avr, Y_STEP_PIN, arduidiot_644);
236 avr_irq_t * d = get_ardu_irq(avr, Y_DIR_PIN, arduidiot_644);
237 avr_irq_t * m = get_ardu_irq(avr, Y_MIN_PIN, arduidiot_644);
239 stepper_init(avr, &r->step_y, "Y", axis_pp_per_mm[1], 100, 200, 0);
240 stepper_connect(&r->step_y, s, d, e, m, stepper_endstop_inverted);
243 avr_irq_t * e = get_ardu_irq(avr, Z_ENABLE_PIN, arduidiot_644);
244 avr_irq_t * s = get_ardu_irq(avr, Z_STEP_PIN, arduidiot_644);
245 avr_irq_t * d = get_ardu_irq(avr, Z_DIR_PIN, arduidiot_644);
246 avr_irq_t * m = get_ardu_irq(avr, Z_MIN_PIN, arduidiot_644);
248 stepper_init(avr, &r->step_z, "Z", axis_pp_per_mm[2], 20, 130, 0);
249 stepper_connect(&r->step_z, s, d, e, m, stepper_endstop_inverted);
252 avr_irq_t * e = get_ardu_irq(avr, E0_ENABLE_PIN, arduidiot_644);
253 avr_irq_t * s = get_ardu_irq(avr, E0_STEP_PIN, arduidiot_644);
254 avr_irq_t * d = get_ardu_irq(avr, E0_DIR_PIN, arduidiot_644);
256 stepper_init(avr, &r->step_e, "E", axis_pp_per_mm[3], 0, 0, 0);
257 stepper_connect(&r->step_e, s, d, e, NULL, 0);
262 int main(int argc, char *argv[])
265 strcpy(path, argv[0]);
266 strcpy(path, dirname(path));
267 strcpy(path, dirname(path));
268 printf("Stripped base directory to '%s'\n", path);
273 for (int i = 1; i < argc; i++)
274 if (!strcmp(argv[i], "-d"))
276 avr = avr_make_mcu_by_name("atmega644");
278 fprintf(stderr, "%s: Error creating the AVR core\n", argv[0]);
281 // snprintf(avr_flash_path, sizeof(avr_flash_path), "%s/%s", pwd, "simduino_flash.bin");
282 strcpy(avr_flash_path, "reprap_flash.bin");
283 // register our own functions
284 avr->special_init = avr_special_init;
285 avr->special_deinit = avr_special_deinit;
287 avr->frequency = 20000000;
288 avr->aref = avr->avcc = avr->vcc = 5 * 1000; // needed for ADC
291 const char * fname = "/opt/reprap/tvrrug/Marlin/Marlin/applet/Marlin.elf";
292 // try to load an ELF file, before trying the .hex
293 if (elf_read_firmware(fname, &f) == 0) {
294 printf("firmware %s f=%d mmcu=%s\n", fname, (int)f.frequency, f.mmcu);
295 avr_load_firmware(avr, &f);
299 // snprintf(path, sizeof(path), "%s/%s", pwd, "ATmegaBOOT_168_atmega328.ihex");
300 strcpy(path, "marlin/Marlin.hex");
301 // strcpy(path, "marlin/bootloader-644-20MHz.hex");
302 uint8_t * boot = read_ihex_file(path, &size, &base);
304 fprintf(stderr, "%s: Unable to load %s\n", argv[0], path);
307 printf("Firmware %04x(%04x in AVR talk): %d bytes (%d words)\n", base, base/2, size, size/2);
308 memcpy(avr->flash + base, boot, size);
311 avr->codeend = avr->flashend;
315 // even if not setup at startup, activate gdb if crashing
316 avr->gdb_port = 1234;
318 printf("AVR is stopped, waiting on gdb on port %d. Use 'target remote :%d' in avr-gdb\n",
319 avr->gdb_port, avr->gdb_port);
320 avr->state = cpu_Stopped;
324 // Marlin doesn't loop, sleep, so we don't know when it's idle
325 // I changed Marlin to do a spurious write to the GPIOR0 register so we can trap it
326 avr_register_io_write(avr, MEGA644_GPIOR0, reprap_relief_callback, NULL);
328 reprap_init(avr, &reprap);
332 pthread_create(&run, NULL, avr_run_thread, NULL);