Add simulation code: use "make sim"

This commit is contained in:
Stephan Walter 2010-10-18 20:15:59 +02:00 committed by Michael Moon
parent c94d2a4f1e
commit 3028b297f3
20 changed files with 531 additions and 23 deletions

View File

@ -89,6 +89,7 @@ program: $(PROGRAM).hex config.h
clean:
rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex *.al *.i *.s *~
rm -f sim
size: $(PROGRAM).elf
@echo " SIZE Atmega168 Atmega328p Atmega644"
@ -123,3 +124,24 @@ config.h: config.h.dist
%.sym: %.elf
@echo " SYM $@"
@$(OBJDUMP) -t $< | perl -ne 'BEGIN { printf " ADDR NAME SIZE\n"; } /([0-9a-f]+)\s+(\w+)\s+O\s+\.(bss|data)\s+([0-9a-f]+)\s+(\w+)/ && printf "0x%04x %-20s +%d\n", eval("0x$$1") & 0xFFFF, $$5, eval("0x$$4")' | sort -k1 > $@
##############################################################################
# #
# Simulation #
# #
##############################################################################
SIM_SOURCES = $(PROGRAM).c serial_sim.c dda.c gcode.c timer_sim.c clock_sim.c temp.c sermsg.c dda_queue.c debug.c sersendf.c heater.c analog_sim.c delay_sim.c simulation.c
SIM_HEADERS = config.h serial.h dda.h gcode.h timer.h clock.h temp.h sermsg.h dda_queue.h debug.h sersendf.h heater.h analog.h delay.h simulation.h
SIM_OBJ = $(patsubst %.c,%.sim.o,${SIM_SOURCES})
SIM_CFLAGS = -g -Wall -Wstrict-prototypes -Os $(DEFS) -std=gnu99 -funsigned-char -funsigned-bitfields -fshort-enums
%.sim.o: %.c $(SIM_HEADERS)
@echo " CC $@"
@cc -DDEBUG -DSIMULATION -c $(SIM_CFLAGS) -o $@ $<
sim: $(SIM_OBJ)
@echo " LINK $@"
@cc $(SIM_CFLAGS) -o $@ $^

17
analog_sim.c Normal file
View File

@ -0,0 +1,17 @@
#include "analog.h"
#include "simulation.h"
static bool analog_initialised = false;
void analog_init(void)
{
sim_info("analog_init: not implemented in simulation");
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;
}

56
clock_sim.c Normal file
View File

@ -0,0 +1,56 @@
#include <signal.h>
#include <stdlib.h>
#include <sys/time.h>
#include "clock.h"
#include "simulation.h"
static uint8_t clock_counter_250ms = 0;
static uint8_t clock_counter_1s = 0;
volatile uint8_t clock_flag = 0;
static bool clock_initialised = false;
#define SIM_CLOCK_SLOWDOWN 50
static void timer2_isr(int cause, siginfo_t *HowCome, void *ucontext)
{
if (!sim_interrupts) return;
sim_interrupts = false;
// 1/4 second tick
if (++clock_counter_250ms == 250 / SIM_CLOCK_SLOWDOWN) {
clock_flag |= CLOCK_FLAG_250MS;
clock_counter_250ms = 0;
if (++clock_counter_1s == 4) {
clock_flag |= CLOCK_FLAG_1S;
clock_counter_1s = 0;
}
}
sim_interrupts = true;
}
void clock_setup(void)
{
struct itimerval itimer;
struct sigaction sa;
long unsigned int usec = 1000 * SIM_CLOCK_SLOWDOWN;
sim_info("clock_setup: simulate timer 2 ISR at %luus", usec);
sa.sa_sigaction = timer2_isr;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
if (sigaction(SIGPROF, &sa, 0)) {
sim_error("sigaction");
}
itimer.it_interval.tv_sec = 0;
itimer.it_interval.tv_usec = 1000 * SIM_CLOCK_SLOWDOWN;
itimer.it_value.tv_sec = 0;
itimer.it_value.tv_usec = 1000 * SIM_CLOCK_SLOWDOWN;
setitimer(ITIMER_PROF, &itimer, NULL);
clock_initialised = true;
}

View File

@ -132,7 +132,9 @@
- comment out pins not in use, as this drops the corresponding code and makes operations faster
*/
#ifndef SIMULATION
#include "arduino.h"
#endif
/*
RESERVED pins

13
dda.c
View File

@ -1,7 +1,10 @@
#include "dda.h"
#include <string.h>
#ifndef SIMULATION
#include <avr/interrupt.h>
#endif
#include "timer.h"
#include "serial.h"
@ -333,7 +336,15 @@ void dda_create(DDA *dda, TARGET *target) {
}
if (debug_flags & DEBUG_DDA) {
sersendf_P(PSTR("\n{DDA:CA end_c:%lu, n:%ld, md:%lu, ssq:%lu, esq:%lu, dsq:%lu, msbssq:%u, msbtot:%u}\n"), dda->end_c >> 8, dda->n, move_duration, ssq, esq, dsq, msb_ssq, msb_tot);
sersendf_P(PSTR("\n{DDA:CA end_c:%lu, n:%ld, md:%lu, ssq:%lu, esq:%lu, dsq:%lu, msbssq:%u, msbtot:%u}\n"),
(long unsigned int)dda->end_c >> 8,
(long int)dda->n,
(long unsigned int)move_duration,
(long unsigned int)ssq,
(long unsigned int)esq,
(long unsigned int)dsq,
msb_ssq,
msb_tot);
}
dda->accel = 1;

View File

@ -1,7 +1,9 @@
#include "dda_queue.h"
#include <string.h>
#ifndef SIMULATION
#include <avr/interrupt.h>
#endif
#include "config.h"
#include "timer.h"

15
delay_sim.c Normal file
View File

@ -0,0 +1,15 @@
#include <unistd.h>
#include "delay.h"
#include "simulation.h"
void delay(uint32_t us)
{
usleep(us);
}
void delay_ms(uint32_t ms)
{
usleep(ms * 1000);
}

View File

@ -2,7 +2,9 @@
#ifdef HEATER_PIN
#ifndef SIMULATION
#include <avr/eeprom.h>
#endif
#include "sersendf.h"
#include "debug.h"

View File

@ -2,6 +2,7 @@
#define _HEATER_H
#include "config.h"
#include "simulation.h"
#ifdef HEATER_PIN

View File

@ -1,6 +1,7 @@
#ifndef SIMULATION
#include <avr/io.h>
#include <avr/interrupt.h>
#endif
#include "config.h"
@ -17,6 +18,7 @@
#include "sersendf.h"
#include "heater.h"
#include "analog.h"
#include "simulation.h"
void io_init(void) {
// disable modules we don't use
@ -127,10 +129,20 @@ void clock_250ms(void) {
ifclock(CLOCK_FLAG_1S) {
if (debug_flags & DEBUG_POSITION) {
// current position
sersendf_P(PSTR("Pos: %ld,%ld,%ld,%ld,%lu\n"), current_position.X, current_position.Y, current_position.Z, current_position.E, current_position.F);
sersendf_P(PSTR("Pos: %ld,%ld,%ld,%ld,%lu\n"),
(long int)current_position.X,
(long int)current_position.Y,
(long int)current_position.Z,
(long int)current_position.E,
(long unsigned int)current_position.F);
// target position
sersendf_P(PSTR("Dst: %ld,%ld,%ld,%ld,%lu\n"), movebuffer[mb_tail].endpoint.X, movebuffer[mb_tail].endpoint.Y, movebuffer[mb_tail].endpoint.Z, movebuffer[mb_tail].endpoint.E, movebuffer[mb_tail].endpoint.F);
sersendf_P(PSTR("Dst: %ld,%ld,%ld,%ld,%lu\n"),
(long int)movebuffer[mb_tail].endpoint.X,
(long int)movebuffer[mb_tail].endpoint.Y,
(long int)movebuffer[mb_tail].endpoint.Z,
(long int)movebuffer[mb_tail].endpoint.E,
(long unsigned int)movebuffer[mb_tail].endpoint.F);
// Queue
print_queue();

View File

@ -2,8 +2,12 @@
#define _SERIAL_H
#include <stdint.h>
#ifndef SIMULATION
#include <avr/io.h>
#include <avr/pgmspace.h>
#endif
#include "simulation.h"
// initialise serial subsystem
void serial_init(void);

116
serial_sim.c Normal file
View File

@ -0,0 +1,116 @@
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <unistd.h>
#include "serial.h"
#include "simulation.h"
static int serial_fd;
static bool serial_initialised = false;
void serial_init(void)
{
struct termios options;
// hack to get argv and argc
extern char ** environ;
int argc = 1;
char **argv = environ - 3;
while((int)*argv != argc)
{
++argc;
--argv;
}
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);
}

View File

@ -1,7 +1,9 @@
#include "sersendf.h"
#include <stdarg.h>
#ifndef SIMULATION
#include <avr/pgmspace.h>
#endif
#include "serial.h"
#include "sermsg.h"
@ -23,14 +25,14 @@ void sersendf(char *format, ...) {
if (j == 4)
serwrite_uint32(va_arg(args, uint32_t));
else
serwrite_uint16(va_arg(args, uint16_t));
serwrite_uint16(va_arg(args, unsigned int));
j = 0;
break;
case 'd':
if (j == 4)
serwrite_int32(va_arg(args, int32_t));
else
serwrite_int16(va_arg(args, int16_t));
serwrite_int16(va_arg(args, int));
j = 0;
break;
case 'p':
@ -39,11 +41,11 @@ void sersendf(char *format, ...) {
if (j == 4)
serwrite_hex32(va_arg(args, uint32_t));
else
serwrite_hex16(va_arg(args, uint16_t));
serwrite_hex16(va_arg(args, unsigned int));
j = 0;
break;
case 'c':
serial_writechar(va_arg(args, uint16_t));
serial_writechar(va_arg(args, unsigned int));
j = 0;
break;
case 's':
@ -86,14 +88,14 @@ void sersendf_P(PGM_P format, ...) {
if (j == 4)
serwrite_uint32(va_arg(args, uint32_t));
else
serwrite_uint16(va_arg(args, uint16_t));
serwrite_uint16(va_arg(args, unsigned int));
j = 0;
break;
case 'd':
if (j == 4)
serwrite_int32(va_arg(args, int32_t));
else
serwrite_int16(va_arg(args, int16_t));
serwrite_int16(va_arg(args, int));
j = 0;
break;
/* case 'x':

View File

@ -1,7 +1,10 @@
#ifndef _SERSENDF_H
#define _SERSENDF_H
#ifndef SIMULATION
#include <avr/pgmspace.h>
#endif
#include "simulation.h"
void sersendf(char *format, ...) __attribute__ ((format (printf, 1, 2)));
void sersendf_P(PGM_P format, ...) __attribute__ ((format (printf, 1, 2)));

105
simulation.c Normal file
View File

@ -0,0 +1,105 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include "simulation.h"
uint8_t ACSR;
uint8_t TIMSK1;
/* -- debugging ------------------------------------------------------------ */
void sim_info(const char fmt[], ...)
{
va_list ap;
fputs("\033[0;32m" , stdout);
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
fputs("\033[m\n", stdout);
}
void sim_error(const char msg[])
{
printf("\033[0;31mERROR: %s\033[m\n", msg);
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)
{
sim_info("x:%5d y:%5d z:%5d e:%5d", x, y, z, e);
}
void WRITE(pin_t pin, bool s)
{
bool old_state = state[pin];
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)
{
direction[pin] = out;
}
void SET_INPUT(pin_t pin)
{
direction[pin] = in;
}

81
simulation.h Normal file
View File

@ -0,0 +1,81 @@
#if !defined _SIMULATION_H && defined SIMULATION
#define _SIMULATION_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
#undef X_STEP_PIN
#undef X_DIR_PIN
#undef X_MIN_PIN
#undef Y_STEP_PIN
#undef Y_DIR_PIN
#undef Y_MIN_PIN
#undef Z_STEP_PIN
#undef Z_DIR_PIN
#undef Z_MIN_PIN
#undef E_STEP_PIN
#undef E_DIR_PIN
#undef STEPPER_ENABLE_PIN
#undef HEATER_PIN
#undef FAN_PIN
#undef HEATER_PWM
#undef FAN_PWM
typedef enum {
X_STEP_PIN,
X_DIR_PIN,
X_MIN_PIN,
Y_STEP_PIN,
Y_DIR_PIN,
Y_MIN_PIN,
Z_STEP_PIN,
Z_DIR_PIN,
Z_MIN_PIN,
E_STEP_PIN,
E_DIR_PIN,
STEPPER_ENABLE_PIN,
SCK,
MOSI,
MISO,
SS,
PIN_NB
} pin_t;
#undef TEMP_PIN_CHANNEL
#define TEMP_PIN_CHANNEL 0
extern uint8_t ACSR;
extern uint8_t TIMSK1;
extern volatile bool sim_interrupts;
void WRITE(pin_t pin, bool on);
void SET_OUTPUT(pin_t pin);
void SET_INPUT(pin_t pin);
void sei(void);
#ifdef USE_WATCHDOG
#define wd_init()
#define wd_reset()
#endif
void sim_info(const char fmt[], ...);
void sim_error(const char msg[]);
void sim_assert(bool cond, const char msg[]);
#endif /* _SIMULATION_H */

4
temp.c
View File

@ -18,7 +18,9 @@
#include "temp.h"
#ifndef SIMULATION
#include <avr/eeprom.h>
#endif
#include "clock.h"
#include "serial.h"
@ -72,6 +74,8 @@ uint16_t temptable[NUMTEMPS][2] PROGMEM = {
#endif
#endif
#include "simulation.h"
uint16_t current_temp = 0;
uint16_t target_temp = 0;

2
temp.h
View File

@ -24,7 +24,7 @@ typedef union {
} max6675_data_format;
#endif
#ifdef TEMP_THERMISTOR
#if defined TEMP_THERMISTOR && !defined SIMULATION
#include <avr/pgmspace.h>
#endif

View File

@ -2,7 +2,10 @@
#define _TIMER_H
#include <stdint.h>
#ifndef SIMULATION
#include <avr/io.h>
#endif
#include "simulation.h"
// time-related constants
#define US * (F_CPU / 1000000)

50
timer_sim.c Normal file
View File

@ -0,0 +1,50 @@
#include <signal.h>
#include <stdlib.h>
#include <sys/time.h>
#include "dda_queue.h"
#include "timer.h"
#include "simulation.h"
static bool timer_initialised = false;
void setupTimerInterrupt(void)
{
disableTimerInterrupt();
sim_info("setupTimerInterrupt");
timer_initialised = true;
}
static void timer1_isr(int cause, siginfo_t *HowCome, void *ucontext)
{
if (!sim_interrupts || !timerInterruptIsEnabled()) return;
sim_interrupts = false;
WRITE(SCK, 1);
queue_step();
WRITE(SCK, 0);
sim_interrupts = true;
}
void setTimer(uint32_t delay)
{
struct itimerval itimer;
struct sigaction sa;
sim_assert(timer_initialised, "timer not initialised");
sa.sa_sigaction = timer1_isr;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
if (sigaction(SIGPROF, &sa, 0)) {
sim_error("sigaction");
}
itimer.it_interval.tv_sec = 0;
itimer.it_interval.tv_usec = (long)delay * 8000000 / F_CPU;
itimer.it_value.tv_sec = 0;
itimer.it_value.tv_usec = itimer.it_interval.tv_usec;
setitimer(ITIMER_PROF, &itimer, NULL);
}