Restore simulation build target.
This code was accidentally removed long ago in a botched merge. This patch recovers it and makes it build again. I've done minimal testing and some necessary cleanup. It compiles and runs, but it probably still has a few dust bunnies here and there. I added registers and pin definitions to simulator.h and simulator/simulator.c which I needed to match my Gen7-based config. Other configs or non-AVR ports will need to define more or different registers. Some registers are 16-bits, some are 8-bit, and some are just constant values (enums). A more clever solution would read in the chip-specific header and produce saner definitions which covered all GPIOs. But this commit just takes the quick and easy path to support my own hardware. Most of this code originated in these commits: commitcbf41dd4adAuthor: Stephan Walter <stephan@walter.name> Date: Mon Oct 18 20:28:08 2010 +0200 document simulation commit3028b297f3Author: Stephan Walter <stephan@walter.name> Date: Mon Oct 18 20:15:59 2010 +0200 Add simulation code: use "make sim" Additional tweaks: Revert va_args processing for AVR, but keep 'int' generalization for simulation. gcc wasn't lying. The sim really aborts without this. Remove delay(us) from simulator (obsolete). Improve the README.sim to demonstrate working pronterface connection to sim. Also fix the build instructions. Appease all stock configs. Stub out intercom and shush usb_serial when building simulator. Pretend to be all chip-types for config appeasement. Replace sim_timer with AVR-simulator timer: The original sim_timer and sim_clock provided direct replacements for timer/clock.c in the main code. But when the main code changed, simcode did not. The main clock.c was dropped and merged into timer.c. Also, the timer.c now has movement calculation code in it in some cases (ACCELERATION_TEMPORAL) and it would be wrong to teach the simulator to do the same thing. Instead, teach the simulator to emulate the AVR Timer1 functionality, reacting to values written to OCR1A and OCR1B timer comparison registers. Whenever OCR1A/B are changed, the sim_setTimer function needs to be called. It is called automatically after a timer event, so changes within the timer ISRs do not need to bother with this. A C++ class could make this requirement go away by noticing the assignment. On the other hand, a chip-agnostic timer.c would help make the main code more portable. The latter cleanup is probably better for us in the long run.
This commit is contained in:
parent
2f81386a7a
commit
452e2e5cd9
32
Makefile-AVR
32
Makefile-AVR
|
|
@ -142,3 +142,35 @@ size: $(BUILDDIR)/$(PROGRAM).elf
|
|||
@$(OBJDUMP) -h $^ | perl -MPOSIX -ne '/.(text)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " FLASH : %5d bytes %3d%% %3d%% %3d%% %3d%%\n", $$a, ceil($$a * 100 / (14 * 1024)), ceil($$a * 100 / (30 * 1024)),ceil($$a * 100 / (62 * 1024)), ceil($$a * 100 / (126 * 1024)) }'
|
||||
@$(OBJDUMP) -h $^ | perl -MPOSIX -ne '/.(data|bss)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " RAM : %5d bytes %3d%% %3d%% %3d%% %3d%%\n", $$a, ceil($$a * 100 / (1 * 1024)), ceil($$a * 100 / (2 * 1024)),ceil($$a * 100 / (4 * 1024)), ceil($$a * 100 / (8 * 1024)) }'
|
||||
@$(OBJDUMP) -h $^ | perl -MPOSIX -ne '/.(eeprom)\s+([0-9a-f]+)/ && do { $$a += eval "0x$$2" }; END { printf " EEPROM: %5d bytes %3d%% %3d%% %3d%% %3d%%\n", $$a, ceil($$a * 100 / (1 * 1024)), ceil($$a * 100 / (2 * 1024)), ceil($$a * 100 / (2 * 1024)), ceil($$a * 100 / (4 * 1024)) }'
|
||||
|
||||
|
||||
##############################################################################
|
||||
# #
|
||||
# Simulator #
|
||||
# #
|
||||
##############################################################################
|
||||
|
||||
SIM_PATH = simulator
|
||||
SIM_SOURCES := $(subst $(SIM_PATH)/,,$(wildcard $(SIM_PATH)/*.c))
|
||||
SIM_SOURCES += $(filter-out $(subst _sim.c,.c,$(SIM_SOURCES)),$(SOURCES))
|
||||
SIM_HEADERS = config.h serial.h dda.h timer.h clock.h temp.h sermsg.h
|
||||
SIM_HEADERS += dda_queue.h debug.h sersendf.h heater.h analog.h delay.h
|
||||
SIM_HEADERS += simulator.h
|
||||
|
||||
SIM_OBJ = $(patsubst %.c,$(BUILDDIR)/%.sim.o,$(SIM_SOURCES))
|
||||
SIM_CFLAGS = -g -Wall -Wstrict-prototypes -Wno-format -Os $(DEFS) -std=gnu99
|
||||
SIM_CFLAGS += -funsigned-char -funsigned-bitfields -fshort-enums -I.. -I.
|
||||
|
||||
# Satisfy all current config chip targets
|
||||
SIM_CFLAGS += -DSIMULATOR -D__AVR_ATmega644P__ -D__AVR_ATmega1280__
|
||||
SIM_CFLAGS +=-D__AVR_ATmega2560__ -D__AVR_ATmega32U4__ -D__AVR_AT90USB1286__
|
||||
|
||||
$(BUILDDIR)/%.sim.o: %.c $(SIM_HEADERS)
|
||||
@echo " CC $@"
|
||||
@cc -DDEBUG -c $(SIM_CFLAGS) -o $@ $<
|
||||
|
||||
sim: $(SIM_OBJ)
|
||||
@echo " LINK $@"
|
||||
@cc $(SIM_CFLAGS) -o $@ $^
|
||||
|
||||
vpath %.c $(SIM_PATH)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
##############################################################################
|
||||
# #
|
||||
# Simulator of AVR-targetted code on a PC #
|
||||
# #
|
||||
##############################################################################
|
||||
|
||||
To compile the simulation code, use
|
||||
|
||||
$ make -f Makefile-AVR sim
|
||||
|
||||
The simulator will open a serial port for communication. If you don't want to
|
||||
connect a null modem cable, you can use 'socat' to connect two serial ports:
|
||||
|
||||
socat -d -d PTY,raw,echo=0 PTY,raw,echo=0
|
||||
2013/10/24 17:42:04 socat[3375] N PTY is /dev/pts/12
|
||||
2013/10/24 17:42:04 socat[3375] N PTY is /dev/pts/13
|
||||
2013/10/24 17:42:04 socat[3375] N starting data transfer loop with FDs [3,3] and [5,5]
|
||||
|
||||
On the first line of output, socat will tell you the name of the virtual serial
|
||||
port. Pass this as an argument to the simulator (in another terminal):
|
||||
|
||||
$ ./sim /dev/pts/12
|
||||
|
||||
Give the other virtual serial port to an application like pronterface.
|
||||
|
||||
Now you can send G-codes from the socat terminal. The simulation code will
|
||||
print any data sent via the firmware's serial interface. Stepper positions
|
||||
will be shown in green, counting a rising slope on the pin as one step.
|
||||
2
analog.h
2
analog.h
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef SIMULATOR
|
||||
#define REFERENCE_AREF 0
|
||||
#define REFERENCE_AVCC 64
|
||||
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega328__) || defined (__AVR_ATmega328P__)
|
||||
|
|
@ -24,6 +25,7 @@
|
|||
#warning in your config.h
|
||||
#error REFERENCE undefined
|
||||
#endif
|
||||
#endif /* SIMULATOR */
|
||||
|
||||
void analog_init(void);
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@
|
|||
#ifndef _ARDUINO_H
|
||||
#define _ARDUINO_H
|
||||
|
||||
#ifndef SIMULATOR
|
||||
#include <avr/io.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
utility functions
|
||||
|
|
@ -66,7 +68,9 @@
|
|||
|
||||
added as necessary or if I feel like it- not a comprehensive list!
|
||||
*/
|
||||
|
||||
#ifdef SIMULATOR
|
||||
#include "simulator.h"
|
||||
#else
|
||||
#if defined (__AVR_ATmega168__) || defined (__AVR_ATmega328__) || \
|
||||
defined (__AVR_ATmega328P__)
|
||||
#include "arduino_168_328p.h"
|
||||
|
|
@ -93,6 +97,7 @@
|
|||
#if defined (__AVR_ATmega32U4__)
|
||||
#include "arduino_32U4.h"
|
||||
#endif
|
||||
#endif /* SIMULATOR */
|
||||
|
||||
#ifndef DIO0_PIN
|
||||
#error pins for this chip not defined in arduino.h! If you write an appropriate pin definition and have this firmware work on your chip, please tell us via the forum thread
|
||||
|
|
|
|||
29
crc.c
29
crc.c
|
|
@ -4,22 +4,23 @@
|
|||
\brief crc16 routine
|
||||
*/
|
||||
|
||||
#ifndef SIMULATOR
|
||||
#include <util/crc16.h>
|
||||
#else
|
||||
|
||||
// avr-libc's _crc16_update is equivalent to the following:
|
||||
//
|
||||
// uint16_t _crc16_update(uint16_t crc, uint8_t a) {
|
||||
// int i;
|
||||
// crc ^= a;
|
||||
// for (i = 0; i < 8; ++i)
|
||||
// {
|
||||
// if (crc & 1)
|
||||
// crc = (crc >> 1) ^ 0xA001;
|
||||
// else
|
||||
// crc = (crc >> 1);
|
||||
// }
|
||||
// return crc;
|
||||
// }
|
||||
// Equivalent to avr-libc's _crc16_update.
|
||||
uint16_t _crc16_update(uint16_t crc, uint8_t a) {
|
||||
int i;
|
||||
crc ^= a;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
if (crc & 1)
|
||||
crc = (crc >> 1) ^ 0xA001;
|
||||
else
|
||||
crc = (crc >> 1);
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** block-at-once CRC16 calculator
|
||||
\param *data data to find crc16 for
|
||||
|
|
|
|||
2
dda.c
2
dda.c
|
|
@ -7,7 +7,9 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#ifndef SIMULATOR
|
||||
#include <avr/interrupt.h>
|
||||
#endif
|
||||
|
||||
#include "dda_maths.h"
|
||||
#include "dda_lookahead.h"
|
||||
|
|
|
|||
|
|
@ -11,7 +11,9 @@
|
|||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <math.h>
|
||||
#ifndef SIMULATOR
|
||||
#include <avr/interrupt.h>
|
||||
#endif
|
||||
|
||||
#include "dda_maths.h"
|
||||
#include "dda.h"
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@
|
|||
*/
|
||||
|
||||
#include <string.h>
|
||||
#ifndef SIMULATOR
|
||||
#include <avr/interrupt.h>
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
#include "timer.h"
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@
|
|||
*/
|
||||
|
||||
#include <string.h>
|
||||
#ifndef SIMULATOR
|
||||
#include <avr/interrupt.h>
|
||||
#endif
|
||||
|
||||
#include "gcode_parse.h"
|
||||
|
||||
|
|
|
|||
1
heater.h
1
heater.h
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "config.h"
|
||||
#include <stdint.h>
|
||||
#include "simulator.h"
|
||||
#include "temp.h"
|
||||
|
||||
#undef DEFINE_HEATER
|
||||
|
|
|
|||
|
|
@ -4,8 +4,10 @@
|
|||
\brief motherboard <-> extruder board protocol
|
||||
*/
|
||||
|
||||
#ifndef SIMULATOR
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#endif
|
||||
#include "memory_barrier.h"
|
||||
|
||||
#include "config.h"
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include <stdint.h>
|
||||
#include "config.h"
|
||||
|
||||
#ifndef enable_transmit
|
||||
#ifdef MOTHERBOARD
|
||||
#define enable_transmit() do { WRITE(TX_ENABLE_PIN,1); UCSR1B &=~MASK(RXEN1); } while(0)
|
||||
#define disable_transmit() do { WRITE(TX_ENABLE_PIN,0); UCSR1B &= ~(MASK(TXCIE1) | MASK(UDRIE1)); UCSR1B |= MASK(RXEN1); } while(0)
|
||||
|
|
@ -11,6 +12,7 @@
|
|||
#define enable_transmit() do { WRITE(TX_ENABLE_PIN,1); UCSR0B &= ~MASK(RXEN0); } while(0)
|
||||
#define disable_transmit() do { WRITE(TX_ENABLE_PIN,0); UCSR0B &= ~(MASK(TXCIE0) | MASK(UDRIE0)); UCSR0B |= MASK(RXEN0); } while(0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/// list of error codes, not many so far...
|
||||
enum {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,12 @@
|
|||
#ifndef _MEMORY_BARRIER_H_
|
||||
#define _MEMORY_BARRIER_H_
|
||||
|
||||
#ifdef SIMULATOR
|
||||
#define CLI_SEI_BUG_MEMORY_BARRIER()
|
||||
#define MEMORY_BARRIER()
|
||||
#define ATOMIC_START
|
||||
#define ATOMIC_END
|
||||
#else
|
||||
#include <util/atomic.h>
|
||||
#include <avr/version.h>
|
||||
|
||||
|
|
@ -38,3 +44,4 @@
|
|||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
12
mendel.c
12
mendel.c
|
|
@ -24,8 +24,10 @@
|
|||
ctrl+d \endcode
|
||||
*/
|
||||
|
||||
#ifndef SIMULATOR
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
#include "fuses.h"
|
||||
|
|
@ -46,6 +48,7 @@
|
|||
#include "arduino.h"
|
||||
#include "clock.h"
|
||||
#include "intercom.h"
|
||||
#include "simulator.h"
|
||||
|
||||
/// initialise all I/O - set pins as input or output, turn off unused subsystems, etc
|
||||
void io_init(void) {
|
||||
|
|
@ -228,8 +231,17 @@ void init(void) {
|
|||
/// this is where it all starts, and ends
|
||||
///
|
||||
/// just run init(), then run an endless loop where we pass characters from the serial RX buffer to gcode_parse_char() and check the clocks
|
||||
#ifdef SIMULATOR
|
||||
int g_argc;
|
||||
char** g_argv;
|
||||
int main (int argc, char** argv)
|
||||
{
|
||||
g_argc = argc;
|
||||
g_argv = argv;
|
||||
#else
|
||||
int main (void)
|
||||
{
|
||||
#endif
|
||||
init();
|
||||
|
||||
// main loop
|
||||
|
|
|
|||
4
pinio.h
4
pinio.h
|
|
@ -7,6 +7,10 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef SIMULATOR
|
||||
#include "simulator.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
Power
|
||||
*/
|
||||
|
|
|
|||
3
serial.h
3
serial.h
|
|
@ -3,8 +3,11 @@
|
|||
|
||||
#include "config.h"
|
||||
#include <stdint.h>
|
||||
#ifndef SIMULATOR
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#endif
|
||||
#include "simulator.h"
|
||||
|
||||
#ifdef USB_SERIAL
|
||||
#include "usb_serial.h"
|
||||
|
|
|
|||
29
sersendf.c
29
sersendf.c
|
|
@ -5,7 +5,9 @@
|
|||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#ifndef SIMULATOR
|
||||
#include <avr/pgmspace.h>
|
||||
#endif
|
||||
|
||||
#include "serial.h"
|
||||
#include "sermsg.h"
|
||||
|
|
@ -94,6 +96,13 @@
|
|||
|
||||
\code sersendf_P(PSTR("X:%ld Y:%ld temp:%u.%d flags:%sx Q%su/%su%c\n"), target.X, target.Y, current_temp >> 2, (current_temp & 3) * 25, dda.allflags, mb_head, mb_tail, (queue_full()?'F':(queue_empty()?'E':' '))) \endcode
|
||||
*/
|
||||
|
||||
#ifdef SIMULATOR
|
||||
#define GET_ARG(T) (va_arg(args, int))
|
||||
#else
|
||||
#define GET_ARG(T) (va_arg(args, T))
|
||||
#endif
|
||||
|
||||
void sersendf_P(PGM_P format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
|
@ -111,36 +120,36 @@ void sersendf_P(PGM_P format, ...) {
|
|||
break;
|
||||
case 'u':
|
||||
if (j == 4)
|
||||
serwrite_uint32(va_arg(args, uint32_t));
|
||||
serwrite_uint32(GET_ARG(uint32_t));
|
||||
else
|
||||
serwrite_uint16(va_arg(args, uint16_t));
|
||||
serwrite_uint16(GET_ARG(uint16_t));
|
||||
j = 0;
|
||||
break;
|
||||
case 'd':
|
||||
if (j == 4)
|
||||
serwrite_int32(va_arg(args, int32_t));
|
||||
serwrite_int32(GET_ARG(uint32_t));
|
||||
else
|
||||
serwrite_int16(va_arg(args, int16_t));
|
||||
serwrite_int16(GET_ARG(uint16_t));
|
||||
j = 0;
|
||||
break;
|
||||
case 'c':
|
||||
serial_writechar(va_arg(args, uint16_t));
|
||||
serial_writechar(GET_ARG(uint16_t));
|
||||
j = 0;
|
||||
break;
|
||||
case 'x':
|
||||
serial_writestr_P(PSTR("0x"));
|
||||
if (j == 4)
|
||||
serwrite_hex32(va_arg(args, uint32_t));
|
||||
serwrite_hex32(GET_ARG(uint32_t));
|
||||
else if (j == 1)
|
||||
serwrite_hex8(va_arg(args, uint16_t));
|
||||
serwrite_hex8(GET_ARG(uint16_t));
|
||||
else
|
||||
serwrite_hex16(va_arg(args, uint16_t));
|
||||
serwrite_hex16(GET_ARG(uint16_t));
|
||||
j = 0;
|
||||
break;
|
||||
/* case 'p':
|
||||
serwrite_hex16(va_arg(args, uint16_t));*/
|
||||
serwrite_hex16(GET_ARG(uint16_t));*/
|
||||
case 'q':
|
||||
serwrite_int32_vf(va_arg(args, int32_t), 3);
|
||||
serwrite_int32_vf(GET_ARG(uint32_t), 3);
|
||||
j = 0;
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
#ifndef _SERSENDF_H
|
||||
#define _SERSENDF_H
|
||||
|
||||
#ifndef SIMULATOR
|
||||
#include <avr/pgmspace.h>
|
||||
#endif
|
||||
#include "simulator.h"
|
||||
|
||||
void sersendf(char *format, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
void sersendf_P(PGM_P format, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
|
|
|
|||
|
|
@ -0,0 +1,165 @@
|
|||
#ifdef SIMULATOR
|
||||
|
||||
#undef X_STEP_PIN
|
||||
#undef X_DIR_PIN
|
||||
#undef X_MIN_PIN
|
||||
#undef X_ENABLE_PIN
|
||||
#undef Y_STEP_PIN
|
||||
#undef Y_DIR_PIN
|
||||
#undef Y_MIN_PIN
|
||||
#undef Y_ENABLE_PIN
|
||||
#undef Z_STEP_PIN
|
||||
#undef Z_DIR_PIN
|
||||
#undef Z_MIN_PIN
|
||||
#undef Z_ENABLE_PIN
|
||||
#undef E_STEP_PIN
|
||||
#undef E_DIR_PIN
|
||||
#undef E_ENABLE_PIN
|
||||
#undef STEPPER_ENABLE_PIN
|
||||
|
||||
#undef PS_MOSFET_PIN
|
||||
#undef PS_ON_PIN
|
||||
#undef RX_ENABLE_PIN
|
||||
#undef TX_ENABLE_PIN
|
||||
#undef X_MAX_PIN
|
||||
#undef Y_MAX_PIN
|
||||
#undef Z_MAX_PIN
|
||||
|
||||
#undef READ
|
||||
#undef WRITE
|
||||
#undef TOGGLE
|
||||
#undef SET_INPUT
|
||||
#undef SET_OUTPUT
|
||||
#undef GET_INPUT
|
||||
#undef GET_OUTPUT
|
||||
|
||||
// Compiler appeasement
|
||||
#undef disable_transmit
|
||||
#undef enable_transmit
|
||||
#define disable_transmit()
|
||||
#define enable_transmit()
|
||||
#undef USB_SERIAL
|
||||
|
||||
#ifndef _SIMULATOR_H
|
||||
#define _SIMULATOR_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define PROGMEM
|
||||
#define PGM_P const char *
|
||||
#define PSTR(x) (x)
|
||||
#define pgm_read_byte(x) (*((uint8_t *)(x)))
|
||||
#define pgm_read_word(x) (*((uint16_t *)(x)))
|
||||
|
||||
#define MASK(PIN) (1 << PIN)
|
||||
#define ACD 7
|
||||
#define OCIE1A 1
|
||||
|
||||
// TODO: Implement simulated EEMEM persistence
|
||||
#define EEMEM
|
||||
#define eeprom_read_dword(ptr32) (*(ptr32))
|
||||
#define eeprom_read_word(ptr16) (*(ptr16))
|
||||
#define eeprom_write_dword(ptr32, i32) (*(ptr32)=i32)
|
||||
#define eeprom_write_word(ptr16, i16) (*(ptr16)=i16)
|
||||
|
||||
typedef enum {
|
||||
// Define pins used
|
||||
X_STEP_PIN,
|
||||
X_DIR_PIN,
|
||||
X_MIN_PIN,
|
||||
X_ENABLE_PIN,
|
||||
Y_STEP_PIN,
|
||||
Y_DIR_PIN,
|
||||
Y_MIN_PIN,
|
||||
Y_ENABLE_PIN,
|
||||
Z_STEP_PIN,
|
||||
Z_DIR_PIN,
|
||||
Z_MIN_PIN,
|
||||
Z_ENABLE_PIN,
|
||||
E_STEP_PIN,
|
||||
E_DIR_PIN,
|
||||
E_ENABLE_PIN,
|
||||
|
||||
STEPPER_ENABLE_PIN,
|
||||
|
||||
SCK,
|
||||
MOSI,
|
||||
MISO,
|
||||
SS,
|
||||
|
||||
RX_ENABLE_PIN,
|
||||
TX_ENABLE_PIN,
|
||||
/*
|
||||
* Not used in the simulator. Add them to this list to enable them if needed.
|
||||
PS_MOSFET_PIN,
|
||||
PS_ON_PIN,
|
||||
X_MAX_PIN,
|
||||
Y_MAX_PIN,
|
||||
Z_MAX_PIN,
|
||||
*/
|
||||
PIN_NB /* End of PINS marker; Put all new pins before this one */
|
||||
} pin_t;
|
||||
|
||||
// AVR stand-ins
|
||||
typedef enum {
|
||||
WGM00 = 0,
|
||||
WGM01,
|
||||
WGM20,
|
||||
WGM21,
|
||||
CS00 = 0,
|
||||
CS02,
|
||||
CS20,
|
||||
CS21,
|
||||
CS22,
|
||||
} masks_t;
|
||||
|
||||
#undef TEMP_PIN_CHANNEL
|
||||
#define TEMP_PIN_CHANNEL 0
|
||||
|
||||
extern uint8_t ACSR;
|
||||
extern uint8_t TIMSK1;
|
||||
extern volatile bool sim_interrupts;
|
||||
|
||||
bool READ(pin_t pin);
|
||||
void WRITE(pin_t pin, bool on);
|
||||
void SET_OUTPUT(pin_t pin);
|
||||
void SET_INPUT(pin_t pin);
|
||||
|
||||
// Simulate AVR interrupts.
|
||||
#define ISR(fn) void fn (void)
|
||||
void TIMER1_COMPA_vect(void);
|
||||
void TIMER1_COMPB_vect(void);
|
||||
|
||||
// Compare-timers for next interrupts.
|
||||
extern uint16_t OCR1A, OCR1B;
|
||||
|
||||
// Interrupt control registers.
|
||||
extern uint16_t TCCR1A, TCCR1B;
|
||||
enum { CS10 = 1 , OCIE1B = 3 };
|
||||
|
||||
#define TCNT1 (sim_tick_counter())
|
||||
void sei(void);
|
||||
|
||||
#ifdef USE_WATCHDOG
|
||||
#define wd_init()
|
||||
#define wd_reset()
|
||||
#endif
|
||||
|
||||
void sim_start(int argc, char ** argv);
|
||||
void sim_info(const char fmt[], ...);
|
||||
void sim_debug(const char fmt[], ...);
|
||||
void sim_error(const char msg[]);
|
||||
void sim_assert(bool cond, const char msg[]);
|
||||
void sim_timer_init(void);
|
||||
void sim_timer_stop(void);
|
||||
void sim_setTimer(void);
|
||||
uint16_t sim_tick_counter(void);
|
||||
|
||||
inline void cli(void);
|
||||
inline void cli() { }
|
||||
|
||||
#define DIO0_PIN "proof of life"
|
||||
|
||||
#endif /* _SIMULATOR_H */
|
||||
#endif /* SIMULATOR */
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
#include "analog.h"
|
||||
#include "simulator.h"
|
||||
|
||||
static bool analog_initialised = false;
|
||||
|
||||
void analog_init(void) {
|
||||
sim_info("analog_init: not implemented in simulator");
|
||||
analog_initialised = true;
|
||||
}
|
||||
|
||||
uint16_t analog_read(uint8_t channel) {
|
||||
sim_assert(analog_initialised, "analog_init() was not called before analog_read()");
|
||||
sim_assert(sim_interrupts, "interrupts disabled");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#include <unistd.h>
|
||||
|
||||
#include "delay.h"
|
||||
#include "simulator.h"
|
||||
|
||||
void delay_ms(uint32_t ms) {
|
||||
usleep(ms * 1000);
|
||||
}
|
||||
|
||||
void delay_us(uint16_t us) {
|
||||
usleep(us);
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
#include "heater.h"
|
||||
|
||||
void heater_init(void) {
|
||||
}
|
||||
|
||||
void heater_set(heater_t index, uint8_t value) {
|
||||
sim_info("heater not implemented in simulator.");
|
||||
}
|
||||
|
||||
void heater_tick(heater_t h, temp_type_t type, uint16_t current_temp, uint16_t target_temp) {
|
||||
}
|
||||
|
||||
uint8_t heaters_all_zero(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef EECONFIG
|
||||
void pid_set_p(heater_t index, int32_t p) {}
|
||||
void pid_set_i(heater_t index, int32_t i) {}
|
||||
void pid_set_d(heater_t index, int32_t d) {}
|
||||
void pid_set_i_limit(heater_t index, int32_t i_limit) {}
|
||||
void heater_save_settings(void) {}
|
||||
#endif /* EECONFIG */
|
||||
|
||||
void heater_print(uint16_t i) {
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
#include "intercom.h"
|
||||
|
||||
/* Intercom stubs here to appease compiler for build testing.
|
||||
* Functionally moot.
|
||||
*/
|
||||
|
||||
void intercom_init(void) {
|
||||
sim_error("simulated intercom is not supported");
|
||||
}
|
||||
|
||||
void send_temperature(uint8_t index, uint16_t temperature) {
|
||||
}
|
||||
|
||||
uint16_t read_temperature(uint8_t index) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef MOTHERBOARD
|
||||
void set_dio(uint8_t index, uint8_t value) {
|
||||
}
|
||||
#else
|
||||
uint8_t get_dio(uint8_t index) {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void set_err(uint8_t err) {
|
||||
}
|
||||
|
||||
uint8_t get_err() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void start_send(void) {
|
||||
}
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "serial.h"
|
||||
#include "simulator.h"
|
||||
|
||||
static int serial_fd;
|
||||
static bool serial_initialised = false;
|
||||
|
||||
extern int g_argc;
|
||||
extern char ** g_argv;
|
||||
|
||||
void serial_init(void) {
|
||||
struct termios options;
|
||||
|
||||
int argc = g_argc;
|
||||
char **argv = g_argv;
|
||||
|
||||
sim_assert(argc >= 2, "please specify a serial port device name");
|
||||
|
||||
sim_info("opening serial port %s", argv[1]);
|
||||
serial_fd = open(argv[1], O_RDWR | O_NOCTTY | O_NDELAY);
|
||||
sim_assert(serial_fd != -1, "couldn't open serial port");
|
||||
sim_assert(isatty(serial_fd), "not a TTY");
|
||||
|
||||
sim_info("configuring port");
|
||||
// Get the current options for the port
|
||||
if (tcgetattr(serial_fd, &options) != 0) {
|
||||
sim_error("tcgetattr");
|
||||
}
|
||||
|
||||
// Set the baud rates
|
||||
cfsetispeed(&options, B115200);
|
||||
cfsetospeed(&options, B115200);
|
||||
|
||||
// Enable the receiver and set local mode
|
||||
options.c_cflag |= (CLOCAL | CREAD);
|
||||
|
||||
options.c_cflag &= ~PARENB;
|
||||
options.c_cflag &= ~CSTOPB;
|
||||
options.c_cflag &= ~CSIZE;
|
||||
options.c_cflag |= CS8;
|
||||
|
||||
// Set the new options for the port
|
||||
if (tcsetattr(serial_fd, TCSANOW, &options) != 0) {
|
||||
sim_error("tcsetattr");
|
||||
}
|
||||
|
||||
// flush tx and rx buffers
|
||||
tcflush(serial_fd, TCIOFLUSH);
|
||||
|
||||
serial_initialised = true;
|
||||
}
|
||||
|
||||
// return number of characters in the receive buffer
|
||||
uint8_t serial_rxchars(void) {
|
||||
int rx_chars_nb;
|
||||
|
||||
sim_assert(serial_initialised, "serial interface not initialised");
|
||||
ioctl(serial_fd, FIONREAD, &rx_chars_nb);
|
||||
return rx_chars_nb;
|
||||
}
|
||||
|
||||
// read one character
|
||||
uint8_t serial_popchar(void) {
|
||||
uint8_t c;
|
||||
ssize_t count;
|
||||
|
||||
sim_assert(serial_initialised, "serial interface not initialised");
|
||||
sim_assert(serial_rxchars() > 0, "no chars to read");
|
||||
count = read(serial_fd, &c, 1);
|
||||
sim_assert(count == 1, "no character in serial RX buffer");
|
||||
return c;
|
||||
}
|
||||
|
||||
// send one character
|
||||
void serial_writechar(uint8_t data) {
|
||||
ssize_t count;
|
||||
sim_assert(serial_initialised, "serial interface not initialised");
|
||||
putchar(data);
|
||||
count = write(serial_fd, &data, 1);
|
||||
sim_assert(count == 1, "could not write to serial port");
|
||||
}
|
||||
|
||||
// read/write many characters
|
||||
void serial_writestr(uint8_t *data) {
|
||||
ssize_t count;
|
||||
const char *str = (char *)data;
|
||||
sim_assert(serial_initialised, "serial interface not initialised");
|
||||
puts(str);
|
||||
count = write(serial_fd, str, strlen(str));
|
||||
sim_assert(count == strlen(str), "could not write to serial port");
|
||||
}
|
||||
|
||||
// write from flash
|
||||
void serial_writestr_P(PGM_P data) {
|
||||
serial_writestr((uint8_t *)data);
|
||||
}
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "simulator.h"
|
||||
|
||||
uint8_t ACSR;
|
||||
uint8_t TIMSK1;
|
||||
uint16_t
|
||||
TCCR0A,
|
||||
TCCR0B,
|
||||
TCCR1A,
|
||||
TCCR1B,
|
||||
TCCR2A,
|
||||
TCCR2B,
|
||||
OCR0B,
|
||||
OCR1A,
|
||||
OCR1B,
|
||||
OCR2A,
|
||||
OCR2B,
|
||||
TIMSK0,
|
||||
TIMSK2;
|
||||
|
||||
volatile uint8_t
|
||||
DIO1_WPORT,
|
||||
DIO2_WPORT,
|
||||
DIO3_WPORT,
|
||||
DIO4_WPORT;
|
||||
|
||||
|
||||
/* -- debugging ------------------------------------------------------------ */
|
||||
|
||||
static void fgreen(void) { fputs("\033[0;32m" , stdout); }
|
||||
static void fred(void) { fputs("\033[0;31m" , stdout); }
|
||||
static void fbreset(void) { fputs("\033[m" , stdout); }
|
||||
|
||||
|
||||
void sim_info(const char fmt[], ...) {
|
||||
va_list ap;
|
||||
fgreen();
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', stdout);
|
||||
fbreset();
|
||||
}
|
||||
|
||||
void sim_debug(const char fmt[], ...) {
|
||||
#ifdef SIM_DEBUG
|
||||
va_list ap;
|
||||
fcyan();
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
fputc('\n', stdout);
|
||||
fbreset();
|
||||
#endif
|
||||
}
|
||||
|
||||
void sim_error(const char msg[]) {
|
||||
fred();
|
||||
printf("ERROR: %s\n", msg);
|
||||
fputc('\n', stdout);
|
||||
fbreset();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void sim_assert(bool cond, const char msg[]) {
|
||||
if (!cond) {
|
||||
sim_error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -- interrupts ----------------------------------------------------------- */
|
||||
|
||||
volatile bool sim_interrupts = false;
|
||||
|
||||
void sei(void) {
|
||||
sim_interrupts = true;
|
||||
}
|
||||
|
||||
|
||||
/* -- PIN I/O ------------------------------------------------------------ */
|
||||
|
||||
#define out true
|
||||
#define in false
|
||||
|
||||
static int x = 0, y = 0, z = 0, e = 0;
|
||||
|
||||
static bool direction[PIN_NB];
|
||||
static bool state[PIN_NB];
|
||||
|
||||
static void print_pos(void) {
|
||||
printf("print_pos: %d, %d, %d, %d\n", x, y, z, e);
|
||||
sim_info("x:%5d y:%5d z:%5d e:%5d", x, y, z, e);
|
||||
}
|
||||
|
||||
bool READ(pin_t pin) {
|
||||
sim_assert(pin < PIN_NB, "READ: Pin number out of range");
|
||||
// Add any necessary reactive pin-handlers here.
|
||||
return state[pin];
|
||||
}
|
||||
|
||||
void WRITE(pin_t pin, bool s) {
|
||||
bool old_state = state[pin];
|
||||
sim_assert(pin < PIN_NB, "WRITE: Pin number out of range");
|
||||
|
||||
if (direction[pin] == out) {
|
||||
state[pin] = s;
|
||||
}
|
||||
if (s && !old_state) { /* rising edge */
|
||||
switch (pin) {
|
||||
case X_STEP_PIN:
|
||||
x += state[X_DIR_PIN] ? 1 : -1;
|
||||
print_pos();
|
||||
break;
|
||||
case Y_STEP_PIN:
|
||||
y += state[Y_DIR_PIN] ? 1 : -1;
|
||||
print_pos();
|
||||
break;
|
||||
case Z_STEP_PIN:
|
||||
z += state[Z_DIR_PIN] ? 1 : -1;
|
||||
print_pos();
|
||||
break;
|
||||
case E_STEP_PIN:
|
||||
e += state[E_DIR_PIN] ? 1 : -1;
|
||||
print_pos();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SET_OUTPUT(pin_t pin) {
|
||||
sim_assert(pin < PIN_NB, "Pin number out of range");
|
||||
direction[pin] = out;
|
||||
}
|
||||
|
||||
void SET_INPUT(pin_t pin) {
|
||||
sim_assert(pin < PIN_NB, "Pin number out of range");
|
||||
direction[pin] = in;
|
||||
}
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "dda_queue.h"
|
||||
#include "timer.h"
|
||||
#include "simulator.h"
|
||||
#include <time.h>
|
||||
#include <stdio.h> // printf
|
||||
#include <unistd.h> // usleep
|
||||
|
||||
#define TIME_SLOW_FACTOR 1
|
||||
|
||||
static void schedule_timer(uint32_t useconds);
|
||||
|
||||
static bool timer_initialised = false;
|
||||
|
||||
enum {
|
||||
// One bit per timer
|
||||
TIMER_OCR1A = 0x1 ,
|
||||
TIMER_OCR1B = 0x2 ,
|
||||
};
|
||||
|
||||
static volatile uint8_t timer_reason; // Who scheduled this timer
|
||||
|
||||
static uint64_t now_us(void) {
|
||||
struct timespec tv;
|
||||
|
||||
int n = clock_gettime(CLOCK_MONOTONIC, &tv);
|
||||
sim_assert(n == 0, "clock_gettime failed");
|
||||
|
||||
// Convert tv to nanoseconds.
|
||||
uint64_t nsec = tv.tv_sec;
|
||||
nsec *= 1000 * 1000 * 1000;
|
||||
nsec += tv.tv_nsec;
|
||||
|
||||
// nanoseconds to microseconds
|
||||
return nsec / 1000;
|
||||
}
|
||||
|
||||
uint16_t sim_tick_counter(void) {
|
||||
// microseconds to 16-bit clock ticks
|
||||
return (now_us() / TIME_SLOW_FACTOR) US;
|
||||
}
|
||||
|
||||
extern uint8_t clock_counter_10ms, clock_counter_250ms, clock_counter_1s;
|
||||
static uint64_t begin;
|
||||
static uint64_t then;
|
||||
void sim_timer_init(void) {
|
||||
then = begin = now_us();
|
||||
sim_info("timer_init");
|
||||
timer_initialised = true;
|
||||
|
||||
sim_setTimer();
|
||||
}
|
||||
|
||||
void sim_timer_stop(void) {
|
||||
sim_info("timer_stop");
|
||||
timer_reason = 0; // Cancel pending timer;
|
||||
}
|
||||
|
||||
static void timer1_isr(int cause, siginfo_t *HowCome, void *ucontext) {
|
||||
if ( ! sim_interrupts) {
|
||||
// Interrupts disabled. Schedule another callback in 10us.
|
||||
schedule_timer(10);
|
||||
return;
|
||||
}
|
||||
|
||||
sim_interrupts = false;
|
||||
|
||||
#ifdef SIM_DEBUG
|
||||
uint64_t now = now_us();
|
||||
static unsigned int cc_1s = 0, prev_1s = 0;
|
||||
|
||||
if ( ! clock_counter_1s && prev_1s) ++cc_1s;
|
||||
prev_1s = clock_counter_1s;
|
||||
|
||||
//uint16_t now = sim_tick_counter();
|
||||
uint64_t real = now-begin;
|
||||
uint64_t avr = cc_1s * 4 + clock_counter_1s;
|
||||
avr *= 250;
|
||||
avr += clock_counter_250ms * 10;
|
||||
avr += clock_counter_10ms;
|
||||
avr *= 1000 ;
|
||||
printf("test: Real: %us %u.%03ums AVR: %us %u.%03ums Real/AVR: %u\n",
|
||||
real / 1000000 , (real % 1000000)/1000 , real % 1000 ,
|
||||
avr / 1000000 , (avr % 1000000)/1000 , avr % 1000 ,
|
||||
real / (avr?avr:1) );
|
||||
printf("test: 10ms=%u 250ms=%u 1s=%u total=%lu actual=%lu\n",
|
||||
clock_counter_10ms, clock_counter_250ms, clock_counter_1s,
|
||||
now - begin , now - then);
|
||||
//printf(" timer1_isr tick_time=%04X now=%04X delta=%u total=%u\n",
|
||||
// TICK_TIME , now, now_us() - then, (now_us() - begin)/1000000 ) ;
|
||||
then = now;
|
||||
#endif
|
||||
|
||||
if (timer_reason & TIMER_OCR1A) TIMER1_COMPA_vect();
|
||||
if (timer_reason & TIMER_OCR1B) TIMER1_COMPB_vect();
|
||||
timer_reason = 0;
|
||||
|
||||
sim_interrupts = true;
|
||||
|
||||
// Setup next timer
|
||||
sim_setTimer();
|
||||
}
|
||||
|
||||
// TODO: Remove 'delay' value and use AVR regs instead
|
||||
void sim_setTimer() {
|
||||
// Set callbacks for COMPA and COMPB timers
|
||||
uint32_t nextA = 0, nextB = 0;
|
||||
uint16_t now = sim_tick_counter();
|
||||
|
||||
sim_assert(timer_initialised, "timer not initialised");
|
||||
|
||||
//-- Calculate time in clock ticks until next timer events
|
||||
if (TIMSK1 & MASK(OCIE1A)) {
|
||||
sim_debug("Timer1 Interrupt A: Enabled");
|
||||
nextA = OCR1A - now;
|
||||
// 0 = No timer; 1-0x10000 = time until next occurrence
|
||||
if ( ! nextA) nextA = 0x10000;
|
||||
}
|
||||
if (TIMSK1 & MASK(OCIE1B)) {
|
||||
sim_debug("Timer1 Interrupt B: Enabled");
|
||||
nextB = OCR1B - now;
|
||||
// 0 = No timer; 1-0x10000 = time until next occurrence
|
||||
if ( ! nextB) nextB = 0x10000;
|
||||
}
|
||||
|
||||
//-- Find the nearest event
|
||||
uint32_t next = nextA;
|
||||
if (nextB && ( ! next || (nextB < next))) {
|
||||
next = nextB;
|
||||
timer_reason = TIMER_OCR1B;
|
||||
}
|
||||
|
||||
//-- Flag the reasons for the next event
|
||||
timer_reason = 0;
|
||||
if (next == nextA) timer_reason |= TIMER_OCR1A;
|
||||
if (next == nextB) timer_reason |= TIMER_OCR1B;
|
||||
|
||||
// FIXME: We will miss events if they occur like this:
|
||||
// nextA = 0x1000
|
||||
// nextB = 0x1001
|
||||
// timer_reason = TIMER_OCR1A
|
||||
// ISR is triggered and finishes at 0x1002
|
||||
// => Next trigger for B will not occur until NEXT 0x1001 comes around
|
||||
// Need some way to notice a missed trigger.
|
||||
// Maybe store 32-bit tick value for next trigger time for each timer.
|
||||
|
||||
//-- Convert ticks to microseconds
|
||||
long actual = ((unsigned long)next) * TIME_SLOW_FACTOR / (1 US);
|
||||
if (next) {
|
||||
sim_debug("OCR1A:%04X OCR1B:%04X now=%04X", OCR1A, OCR1B, now );
|
||||
sim_debug(" next=%u real=%u", next, actual);
|
||||
}
|
||||
|
||||
//-- Schedule the event
|
||||
schedule_timer(actual);
|
||||
}
|
||||
|
||||
// Schedule Timer1 callback useconds from now.
|
||||
// Zero cancels any pending timer.
|
||||
static void schedule_timer(uint32_t useconds) {
|
||||
struct itimerval itimer;
|
||||
struct sigaction sa;
|
||||
|
||||
sa.sa_sigaction = timer1_isr;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
if (sigaction(SIGALRM, &sa, 0)) {
|
||||
sim_error("sigaction");
|
||||
}
|
||||
itimer.it_interval.tv_sec = 0;
|
||||
itimer.it_interval.tv_usec = 0; // If signal occurs , trigger again in 10us
|
||||
itimer.it_value.tv_sec = useconds / 1000000;
|
||||
itimer.it_value.tv_usec = useconds % 1000000;
|
||||
setitimer(ITIMER_REAL, &itimer, NULL);
|
||||
}
|
||||
7
temp.c
7
temp.c
|
|
@ -7,8 +7,11 @@
|
|||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#ifndef SIMULATOR
|
||||
#include <avr/eeprom.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#endif
|
||||
#include "simulator.h"
|
||||
|
||||
#include "arduino.h"
|
||||
#include "debug.h"
|
||||
|
|
@ -47,7 +50,11 @@ typedef struct {
|
|||
|
||||
#undef DEFINE_TEMP_SENSOR
|
||||
/// help build list of sensors from entries in config.h
|
||||
#ifndef SIMULATOR
|
||||
#define DEFINE_TEMP_SENSOR(name, type, pin, additional) { (type), (pin ## _ADC), (HEATER_ ## name), (additional) },
|
||||
#else
|
||||
#define DEFINE_TEMP_SENSOR(name, type, pin, additional) { (type), (TEMP_SENSOR_ ## name), (HEATER_ ## name), (additional) },
|
||||
#endif
|
||||
static const temp_sensor_definition_t temp_sensors[NUM_TEMP_SENSORS] =
|
||||
{
|
||||
#include "config.h"
|
||||
|
|
|
|||
14
timer.c
14
timer.c
|
|
@ -10,7 +10,9 @@
|
|||
Teacup has tried numerous timer management methods, and this is the best so far.
|
||||
*/
|
||||
|
||||
#ifndef SIMULATOR
|
||||
#include <avr/interrupt.h>
|
||||
#endif
|
||||
#include "memory_barrier.h"
|
||||
|
||||
#include "arduino.h"
|
||||
|
|
@ -119,6 +121,10 @@ void timer_init()
|
|||
OCR1B = TICK_TIME & 0xFFFF;
|
||||
// enable interrupt
|
||||
TIMSK1 = MASK(OCIE1B);
|
||||
#ifdef SIMULATOR
|
||||
// Tell simulator
|
||||
sim_timer_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MOTHERBOARD
|
||||
|
|
@ -201,11 +207,19 @@ void setTimer(uint32_t delay)
|
|||
// timer1a interrupt to the far side of the return, protecting the
|
||||
// stack from recursively clobbering memory.
|
||||
TIMSK1 |= MASK(OCIE1A);
|
||||
#ifdef SIMULATOR
|
||||
// Tell simulator
|
||||
sim_setTimer();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// stop timers - emergency stop
|
||||
void timer_stop() {
|
||||
// disable all interrupts
|
||||
TIMSK1 = 0;
|
||||
#ifdef SIMULATOR
|
||||
// Tell simulator
|
||||
sim_timer_stop();
|
||||
#endif
|
||||
}
|
||||
#endif /* ifdef MOTHERBOARD */
|
||||
|
|
|
|||
3
timer.h
3
timer.h
|
|
@ -2,7 +2,10 @@
|
|||
#define _TIMER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#ifndef SIMULATOR
|
||||
#include <avr/io.h>
|
||||
#endif
|
||||
#include "simulator.h"
|
||||
|
||||
// time-related constants
|
||||
#define US * (F_CPU / 1000000)
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
// 2012-10-17: Import to Teacup firmware
|
||||
|
||||
#include "config.h"
|
||||
#include "simulator.h"
|
||||
|
||||
/* protect this file from Arduino IDE */
|
||||
#ifdef USB_SERIAL
|
||||
|
|
|
|||
Loading…
Reference in New Issue