diff --git a/.gitignore b/.gitignore index 844cd7a..326f9fc 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ *.elf *.DS_Store *.d +*~ +\#*\# diff --git a/config.h b/config.h index ccba270..6a1f77c 100644 --- a/config.h +++ b/config.h @@ -84,7 +84,7 @@ // parser state depending on user preferences. #define N_STARTUP_LINE 2 // Integer (1-3) -// Allows GRBL to tranck and report gcode line numbers. Enabling this means that the planning buffer +// Allows GRBL to track and report gcode line numbers. Enabling this means that the planning buffer // goes from 18 or 16 to make room for the additional line number data in the plan_block_t struct // #define USE_LINE_NUMBERS // Disabled by default. Uncomment to enable. diff --git a/coolant_control.c b/coolant_control.c index 60cbf2f..3c1a681 100644 --- a/coolant_control.c +++ b/coolant_control.c @@ -46,7 +46,8 @@ void coolant_stop() void coolant_run(uint8_t mode) { if (sys.state == STATE_CHECK_MODE) { return; } - + + protocol_auto_cycle_start(); protocol_buffer_synchronize(); // Ensure coolant turns on when specified in program. if (mode == COOLANT_FLOOD_ENABLE) { COOLANT_FLOOD_PORT |= (1 << COOLANT_FLOOD_BIT); diff --git a/gcode.c b/gcode.c index 8557956..cdef3ad 100644 --- a/gcode.c +++ b/gcode.c @@ -62,7 +62,7 @@ void gc_sync_position() { uint8_t i; for (i=0; i. -OBJECTS = main.o simulator.o runtime.o ../protocol.o ../planner.o ../settings.o ../print.o ../nuts_bolts.o eeprom.o serial.o avr/pgmspace.o avr/interrupt.o util/delay.o util/floatunsisf.o ../stepper.o ../gcode.o ../spindle_control.o ../motion_control.o ../limits.o ../report.o ../coolant_control.o +PLATFORM = LINUX + +OBJECTS = main.o simulator.o serial.o ../main.o ../protocol.o ../planner.o ../settings.o ../print.o ../nuts_bolts.o eeprom.o ../serial.o avr/pgmspace.o avr/interrupt.o avr/io.o util/delay.o util/floatunsisf.o ../stepper.o ../gcode.o ../spindle_control.o ../motion_control.o ../limits.o ../report.o ../coolant_control.o ../probe.o ../system.o kbhit.o platform_$(PLATFORM).o CLOCK = 16000000 EXE_NAME = grbl_sim.exe -COMPILE = $(CC) -Wall -Os -DF_CPU=$(CLOCK) -include config.h -I. - +COMPILE = $(CC) -Wall -g -DF_CPU=$(CLOCK) -include config.h -I. -DPLAT_$(PLATFORM) +LINUX_LIBRARIES = -lrt -pthread # symbolic targets: all: main @@ -30,15 +32,18 @@ clean: # file targets: main: $(OBJECTS) - $(COMPILE) -o $(EXE_NAME) $(OBJECTS) -lm + $(COMPILE) -o $(EXE_NAME) $(OBJECTS) -lm -lrt $($(PLATFORM)_LIBRARIES) %.o: %.c - $(COMPILE) -c $< -o $@ - -../protocol.o: ../protocol.c - $(COMPILE) -include rename_execute_runtime.h -c $< -o $@ + $(COMPILE) -c $< -o $@ ../planner.o: ../planner.c $(COMPILE) -include planner_inject_accessors.c -c $< -o $@ +../serial.o: ../serial.c + $(COMPILE) -include serial_hooks.h -c $< -o $@ + +../main.o: ../main.c + $(COMPILE) -include rename_main.h -c $< -o $@ + diff --git a/sim/avr/interrupt.c b/sim/avr/interrupt.c index 10b5225..2bcbe0d 100644 --- a/sim/avr/interrupt.c +++ b/sim/avr/interrupt.c @@ -21,23 +21,115 @@ */ #include "interrupt.h" +#include "io.h" + +//pseudo-Interrupt vector table +isr_fp compa_vect[6]={0}; +isr_fp compb_vect[6]={0}; +isr_fp ovf_vect[6]={0}; + + +void sei() {io.sreg|=SEI;} +void cli() {io.sreg&=~SEI;} + + + +int16_t sim_scaling[8]={0,1,8,64,256,1024,1,1}; //clock scalars +//Timer/Counter modes: these are incomplete, but enough for this application +enum sim_wgm_mode { + wgm_NORMAL, + wgm_CTC, + wgm_FAST_PWM, + wgm_PHASE_PWM, + wgm_PH_F_PWM, + wgm_RESERVED +}; + +enum sim_wgm_mode sim_wgm0[4] = {wgm_NORMAL,wgm_PHASE_PWM,wgm_CTC,wgm_FAST_PWM}; +enum sim_wgm_mode sim_wgmN[8] = {wgm_NORMAL,wgm_PHASE_PWM,wgm_PHASE_PWM,wgm_PH_F_PWM, + wgm_CTC, wgm_FAST_PWM, wgm_FAST_PWM, wgm_FAST_PWM}; + +void timer_interrupts() { + int i; + uint8_t ien = io.sreg&SEI; //interrupts enabled? + io.prescaler++; + + //all clocks + for (i=0;i<2;i++){ + + uint8_t cs = io.tccrb[i]&7; //clock select bits + int16_t increment = sim_scaling[cs]; + //check scaling to see if timer fires + if (increment && (io.prescaler&(increment-1))==0) { + + //select waveform generation mode + enum sim_wgm_mode mode; + if (i==0 || i==2) { //(T0 and T2 are different from rest) + uint8_t wgm = io.tccra[i]&3; //look at low 2 bits + mode = sim_wgm0[wgm]; + } + else { + uint8_t wgm = ((io.tccrb[i]&8)>>1) | (io.tccra[i]&3); //only using 3 bits for now + mode = sim_wgmN[wgm]; + } + + //tick + io.tcnt[i]++; + //comparators + if ((io.timsk[i]&(1< - -// dummy register variables -extern uint16_t timsk0; -extern uint16_t timsk1; -extern uint16_t timsk2; -extern uint16_t tcnt0; -extern uint16_t tcnt2; -extern uint16_t tccr0b; -extern uint16_t tccr0a; -extern uint16_t tccr2a; -extern uint16_t tccr2b; -extern uint16_t tccr1b; -extern uint16_t tccr1a; -extern uint16_t ocr1a; -extern uint16_t ocr2a; -extern uint16_t pcmsk0; -extern uint16_t pcicr; - // macros to turn avr interrupts into regular functions -#define TIMER1_COMPA_vect +//#define TIMER1_COMPA_vect #define ISR(a) void interrupt_ ## a () -// enable interrupts does nothing in the simulation environment +// Stub of the timer interrupt functions we need +void interrupt_TIMER0_COMPA_vect(); +void interrupt_TIMER1_COMPA_vect(); +void interrupt_TIMER0_OVF_vect(); +void interrupt_SERIAL_UDRE(); +void interrupt_SERIAL_RX(); + + +//pseudo-Interrupt vector table +typedef void(*isr_fp)(void); +extern isr_fp compa_vect[6]; +extern isr_fp compb_vect[6]; +extern isr_fp ovf_vect[6]; + + +// enable interrupts now does something in the simulation environment +#define SEI 0x80 void sei(); void cli(); -// dummy macros for interrupt related registers -#define TIMSK0 timsk0 -#define TIMSK1 timsk1 -#define TIMSK2 timsk2 -#define OCR1A ocr1a -#define OCR2A ocr2a -#define OCIE1A 0 -#define OCIE2A 0 -#define TCNT0 tcnt0 -#define TCNT2 tcnt2 -#define TCCR0B tccr0b -#define TCCR0A tccr0a -#define TCCR1A tccr1a -#define TCCR1B tccr1b -#define TCCR2A tccr2a -#define TCCR2B tccr2b -#define CS21 0 -#define CS10 0 -#define WGM13 0 -#define WGM12 0 -#define WGM11 0 -#define WGM10 0 -#define WGM21 0 -#define COM1A0 0 -#define COM1B0 0 -#define TOIE0 0 -#define TOIE2 0 -#define PCICR pcicr +//simulate timer operation +void timer_interrupts(); + + #endif diff --git a/sim/avr/io.c b/sim/avr/io.c new file mode 100644 index 0000000..8290fec --- /dev/null +++ b/sim/avr/io.c @@ -0,0 +1,4 @@ +#include "io.h" + +// dummy register variables +volatile io_sim_t io={{0}}; diff --git a/sim/avr/io.h b/sim/avr/io.h index 885021a..df8a515 100644 --- a/sim/avr/io.h +++ b/sim/avr/io.h @@ -1,5 +1,6 @@ /* - io.h - dummy replacement for the avr include of the same name + interrupt.h - replacement for the avr include of the same name to provide + dummy register variables and macros Part of Grbl Simulator @@ -19,3 +20,182 @@ along with Grbl. If not, see . */ + +#ifndef io_h +#define io_h + +#include + +union hilo16 { + uint16_t w; + struct { + uint8_t l; //TODO: check that these are right order on x86. Doesn't matter for current usage, but might someday + uint8_t h; + }; +}; + +enum { + SIM_A, SIM_B, SIM_C, SIM_D, SIM_E, + SIM_F, SIM_G, SIM_H, SIM_J, SIM_K, SIM_L, + SIM_PORT_COUNT +}; + +#define SIM_N_TIMERS 6 + + +// dummy register variables +typedef struct io_sim { + uint8_t ddr[SIM_PORT_COUNT]; + uint8_t port[SIM_PORT_COUNT]; + uint8_t pin[SIM_PORT_COUNT]; + uint8_t timsk[SIM_N_TIMERS]; + uint16_t ocra[SIM_N_TIMERS]; + uint16_t ocrb[SIM_N_TIMERS]; + uint16_t ocrc[SIM_N_TIMERS]; + uint16_t tcnt[SIM_N_TIMERS]; //tcint0 is really only 8bit + uint8_t tccra[SIM_N_TIMERS]; + uint8_t tccrb[SIM_N_TIMERS]; + uint8_t tifr[SIM_N_TIMERS]; + uint8_t pcicr; + uint8_t pcmsk[3]; + uint8_t ucsr0[3]; + uint8_t udr[3]; + union hilo16 ubrr0; + + uint16_t prescaler; //continuously running + uint8_t sreg; + + +} io_sim_t; +volatile extern io_sim_t io; + + + + +// dummy macros for interrupt related registers +#define PORTA io.port[SIM_A] +#define PORTB io.port[SIM_B] +#define PORTC io.port[SIM_C] +#define PORTD io.port[SIM_D] +#define PORTE io.port[SIM_E] +#define PORTF io.port[SIM_F] +#define PORTG io.port[SIM_G] +#define PORTH io.port[SIM_H] +#define PORTJ io.port[SIM_J] +#define PORTK io.port[SIM_K] +#define PORTL io.port[SIM_L] + +#define DDRA io.ddr[SIM_A] +#define DDRB io.ddr[SIM_B] +#define DDRC io.ddr[SIM_C] +#define DDRD io.ddr[SIM_D] +#define DDRE io.ddr[SIM_E] +#define DDRF io.ddr[SIM_F] +#define DDRG io.ddr[SIM_G] +#define DDRH io.ddr[SIM_H] +#define DDRJ io.ddr[SIM_J] + +#define PINA io.pin[SIM_A] +#define PINB io.pin[SIM_B] +#define PINC io.pin[SIM_C] +#define PIND io.pin[SIM_D] +#define PINE io.pin[SIM_E] +#define PINF io.pin[SIM_F] +#define PING io.pin[SIM_G] +#define PINH io.pin[SIM_H] +#define PINJ io.pin[SIM_J] +#define PINK io.pin[SIM_K] +#define PINL io.pin[SIM_L] + + +#define TIMSK0 io.timsk[0] +#define TIMSK1 io.timsk[1] +#define TIMSK2 io.timsk[2] +#define TIMSK3 io.timsk[3] +#define TIMSK4 io.timsk[4] +#define TIMSK5 io.timsk[5] + + +#define SIM_TOV 0 +#define SIM_OCA 1 +#define SIM_OCB 2 +#define SIM_OCC 3 +#define SIM_ICI 5 + +#define OCIE0A SIM_OCA +#define OCIE0B SIM_OCB +#define TOIE0 SIM_TOV + +#define ICIE1 SIM_ICI +#define OCIE1C SIM_OCC +#define OCIE1B SIM_OCB +#define OCIE1A SIM_OCA +#define TOIE1 SIM_ICI + +#define ICIE2 SIM_ICI +#define OCIE2C SIM_OCC +#define OCIE2B SIM_OCB +#define OCIE2A SIM_OCA +#define TOIE2 SIM_TOV + +#define OCR0A io.ocra[0] +#define OCR1A io.ocra[1] +#define OCR2A io.ocra[2] + //There are more.. + + +#define TCNT0 io.tcnt[0] +#define TCNT1 io.tcnt[1] +#define TCNT2 io.tcnt[2] + +#define TCCR0B io.tccra[0] +#define TCCR0A io.tccrb[0] +#define TCCR1A io.tccra[1] +#define TCCR1B io.tccrb[1] +#define TCCR2A io.tccra[2] +#define TCCR2B io.tccrb[2] + +#define CS00 0 +#define CS01 1 +#define CS12 2 +#define CS11 1 +#define CS10 0 +#define CS21 1 + +#define WGM13 4 +#define WGM12 3 +#define WGM11 1 +#define WGM10 0 +#define WGM21 1 + +#define COM1A1 7 +#define COM1A0 6 +#define COM1B1 5 +#define COM1B0 4 +#define COM1C1 3 +#define COM1C0 2 + + +#define PCICR io.pcicr +#define PCIE0 0 +#define PCIE1 1 + +//serial channel +#define UCSR0A io.ucsr0[SIM_A] +#define UCSR0B io.ucsr0[SIM_B] +#define UDR0 io.udr[0] +#define UDRIE0 0 +#define RXCIE0 1 +#define RXEN0 2 +#define TXEN0 3 +#define U2X0 4 +#define UBRR0H io.ubrr0.h +#define UBRR0L io.ubrr0.l + +#define PCMSK0 io.pcmsk[0] +#define PCMSK1 io.pcmsk[1] +#define PCMSK2 io.pcmsk[2] + + + +#endif diff --git a/sim/avr/wdt.h b/sim/avr/wdt.h new file mode 100644 index 0000000..482f4fd --- /dev/null +++ b/sim/avr/wdt.h @@ -0,0 +1 @@ +uint16_t wdt; diff --git a/sim/config.h b/sim/config.h index 404accd..5baa20c 100644 --- a/sim/config.h +++ b/sim/config.h @@ -24,94 +24,5 @@ #include "../config.h" #include - -// dummy register variables implemented in simulator.c -extern uint8_t stepping_ddr; -extern uint8_t stepping_port; -extern uint8_t spindle_ddr; -extern uint8_t spindle_port; -extern uint8_t limit_ddr; -extern uint8_t limit_port; -extern uint8_t limit_int_reg; -extern uint8_t pinout_ddr; -extern uint8_t pinout_port; -extern uint8_t pinout_int_reg; -extern uint8_t coolant_flood_ddr; -extern uint8_t coolant_flood_port; - -// ReDefine pin-assignments -#undef STEPPING_DDR -#define STEPPING_DDR stepping_ddr -#undef STEPPING_PORT -#define STEPPING_PORT stepping_port -#undef X_STEP_BIT -#define X_STEP_BIT 2 // Uno Digital Pin 2 -#undef Y_STEP_BIT -#define Y_STEP_BIT 3 // Uno Digital Pin 3 -#undef Z_STEP_BIT -#define Z_STEP_BIT 4 // Uno Digital Pin 4 -#undef X_DIRECTION_BIT -#define X_DIRECTION_BIT 5 // Uno Digital Pin 5 -#undef Y_DIRECTION_BIT -#define Y_DIRECTION_BIT 6 // Uno Digital Pin 6 -#undef Z_DIRECTION_BIT -#define Z_DIRECTION_BIT 7 // Uno Digital Pin 7 - -#undef STEPPERS_DISABLE_DDR -#define STEPPERS_DISABLE_DDR stepping_ddr -#undef STEPPERS_DISABLE_PORT -#define STEPPERS_DISABLE_PORT stepping_port -#undef STEPPERS_DISABLE_BIT -#define STEPPERS_DISABLE_BIT 0 // Uno Digital Pin 8 - -#undef LIMIT_DDR -#define LIMIT_DDR limit_ddr -#undef LIMIT_PORT -#define LIMIT_PORT limit_port -#undef LIMIT_PIN -#define LIMIT_PIN limit_port -#undef X_LIMIT_BIT -#define X_LIMIT_BIT 1 // Uno Digital Pin 9 -#undef Y_LIMIT_BIT -#define Y_LIMIT_BIT 2 // Uno Digital Pin 10 -#undef Z_LIMIT_BIT -#define Z_LIMIT_BIT 3 // Uno Digital Pin 11 -#undef LIMIT_INT -#define LIMIT_INT 0 -#undef LIMIT_PCMSK -#define LIMIT_PCMSK limit_int_reg - -#undef SPINDLE_ENABLE_DDR -#define SPINDLE_ENABLE_DDR spindle_ddr -#undef SPINDLE_ENABLE_PORT -#define SPINDLE_ENABLE_PORT spindle_port -#undef SPINDLE_ENABLE_BIT -#define SPINDLE_ENABLE_BIT 4 // Uno Digital Pin 12 - -#undef SPINDLE_DIRECTION_DDR -#define SPINDLE_DIRECTION_DDR spindle_ddr -#undef SPINDLE_DIRECTION_PORT -#define SPINDLE_DIRECTION_PORT spindle_port -#undef SPINDLE_DIRECTION_BIT -#define SPINDLE_DIRECTION_BIT 5 // Uno Digital Pin 13 - -#undef PINOUT_DDR -#define PINOUT_DDR pinout_ddr -#undef PINOUT_PORT -#define PINOUT_PORT pinout_port -#undef PINOUT_PIN -#define PINOUT_PIN pinout_port -#undef PINOUT_PCMSK -#define PINOUT_PCMSK pinout_int_reg -#undef PINOUT_INT -#define PINOUT_INT 0 - -#undef COOLANT_FLOOD_DDR -#define COOLANT_FLOOD_DDR coolant_flood_ddr -#undef COOLANT_FLOOD_PORT -#define COOLANT_FLOOD_PORT coolant_flood_port -#undef COOLANT_FLOOD_BIT -#define COOLANT_FLOOD_BIT 0 - - +#define AUTO_REPORT_MOVE_DONE #endif diff --git a/sim/eeprom.c b/sim/eeprom.c index 5c3c3f3..0291e85 100644 --- a/sim/eeprom.c +++ b/sim/eeprom.c @@ -21,18 +21,75 @@ */ // These are never called in the simulator +#include +#define MAX_EEPROM_SIZE 4096 //4KB EEPROM in Mega + + +FILE* eeprom_create_empty_file(){ + FILE* fp = fopen("EEPROM.DAT","w+b"); + int i; + if (fp){ + for(i=0;i 0; size--) { + checksum = (checksum << 1) || (checksum >> 7); + checksum += *source; + eeprom_put_char(destination++, *(source++)); + } + eeprom_put_char(destination, checksum); } int memcpy_from_eeprom_with_checksum(char *destination, unsigned int source, unsigned int size) { - return 0; + unsigned char data, checksum = 0; + for(; size > 0; size--) { + data = eeprom_get_char(source++); + checksum = (checksum << 1) || (checksum >> 7); + checksum += data; + *(destination++) = data; + } + return(checksum == eeprom_get_char(source)); } // end of file diff --git a/sim/eeprom.h b/sim/eeprom.h new file mode 100644 index 0000000..6b9a562 --- /dev/null +++ b/sim/eeprom.h @@ -0,0 +1,3 @@ + +#include "../eeprom.h" +void eeprom_close(); diff --git a/sim/kbhit.c b/sim/kbhit.c new file mode 100644 index 0000000..7fc6e9e --- /dev/null +++ b/sim/kbhit.c @@ -0,0 +1,6 @@ +#include +#include + +#include "kbhit.h" + + diff --git a/sim/runtime.c b/sim/kbhit.h similarity index 50% rename from sim/runtime.c rename to sim/kbhit.h index 1b38d6a..7ce1a91 100644 --- a/sim/runtime.c +++ b/sim/kbhit.h @@ -1,38 +1,39 @@ -/* - runtime.c - replacement for the modul of the same name in grbl - Run time commands are not processed in the simulator. - Instead, the execute_runtime() is used as a hook to handle stepper simulation - and printing of simulation results. - - Part of Grbl Simulator - - Copyright (c) 2012 Jens Geisler - - Grbl 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. - - Grbl 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 Grbl. If not, see . -*/ - -#include "simulator.h" -#include - -void orig_protocol_execute_runtime(void); - -// replacement for original execute_runtime as a hook to print blocks as they are generated -// and to control simulation of buffered blocks -void protocol_execute_runtime(void) { - orig_protocol_execute_runtime(); - //printf("printBlock():\n"); - printBlock(); - //printf("handle_buffer():\n"); - handle_buffer(); -} +/* + kbhit.h - keyboard hit detection - used in serial port replacement for grbl sim + + linux kbhit taken from http://cboard.cprogramming.com/c-programming/63166-kbhit-linux.html. + By 'thanatos':http://cboard.cprogramming.com/member.php?u=380 + + Part of Grbl Simulator + + Copyright (c) 2014 Adam Shelly + + Grbl 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. + + Grbl 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 Grbl. If not, see . +*/ + +//if linux +#include +#include +#include + +int kbhit(void); +void enable_kbhit(int); + + +//else +//#include +//#define enable_kbhit(e) +//#define kbhit _kbhit +//endif + diff --git a/sim/main.c b/sim/main.c index d157ac3..e2a4e2e 100644 --- a/sim/main.c +++ b/sim/main.c @@ -34,18 +34,106 @@ #include "simulator.h" +arg_vars_t args; +const char* progname; + +int usage(const char* badarg){ + if (badarg){ + printf("Unrecognized option %s\n",badarg); + } + printf("Usage: \n" + "%s [options] [time_step] [block_file]\n" + " Options:\n" + " -r : minimum time step for printing stepper values. Default=0=no print.\n" + " -t