--- /dev/null
+#include <stdint.h>\r
+#include <string.h>\r
+\r
+#include <avr/interrupt.h>\r
+\r
+#include "intercom.h"\r
+#include "analog.h"\r
+#include "config.h"\r
+#include "watchdog.h"\r
+#include "heater.h"\r
+#include "temp.h"\r
+#include "timer.h"\r
+\r
+static uint8_t motor_pwm;\r
+static uint8_t motor_idle_counter;\r
+\r
+void io_init(void) {\r
+ // setup I/O pins\r
+ WRITE(DEBUG_LED, 0); SET_OUTPUT(DEBUG_LED);\r
+ WRITE(H1D,0); SET_OUTPUT(H1D);\r
+ WRITE(H1E,0); SET_OUTPUT(H1E);\r
+ WRITE(H2D,0); SET_OUTPUT(H2D);\r
+ WRITE(H2E,0); SET_OUTPUT(H2E);\r
+\r
+ SET_INPUT(TRIM_POT);\r
+ SET_INPUT(TEMP_PIN);\r
+ SET_INPUT(TEMP_BED_PIN);\r
+ SET_INPUT(E_STEP_PIN);\r
+ SET_INPUT(E_DIR_PIN);\r
+\r
+ // use pull up resistors to avoid noise\r
+ WRITE(E_STEP_PIN, 1);\r
+ WRITE(E_DIR_PIN, 1);\r
+\r
+ //Enable the RS485 transceiver\r
+ SET_OUTPUT(RX_ENABLE_PIN);\r
+ SET_OUTPUT(TX_ENABLE_PIN);\r
+ WRITE(RX_ENABLE_PIN,0);\r
+ disable_transmit();\r
+\r
+ #ifdef HEATER_PIN\r
+ WRITE(HEATER_PIN, 0); SET_OUTPUT(HEATER_PIN);\r
+ #endif\r
+\r
+ #ifdef BED_PIN\r
+ WRITE(BED_PIN, 0); SET_OUTPUT(BED_PIN);\r
+ #endif\r
+\r
+ #ifdef FAN_PIN\r
+ WRITE(FAN_PIN, 0); SET_OUTPUT(FAN_PIN);\r
+ #endif\r
+\r
+// #if defined(HEATER_PWM) || defined(FAN_PWM) || defined(BED_PWM)\r
+ // setup PWM timer: fast PWM, no prescaler\r
+ TCCR2A = MASK(WGM21) | MASK(WGM20);\r
+ TCCR2B = MASK(CS22);\r
+ TIMSK2 = 0;\r
+ OCR2A = 0;\r
+ OCR2B = 0;\r
+// #endif\r
+\r
+ #if defined(H1E_PWM) && defined(H2E_PWM)\r
+ TCCR0A = MASK(WGM01) | MASK(WGM00);\r
+ TCCR0B = MASK(CS20);\r
+ TIMSK0 = 0;\r
+ OCR0A = 0;\r
+ OCR0B = 0;\r
+ #endif\r
+}\r
+\r
+void motor_init(void) {\r
+ //Enable an interrupt to be triggered when the step pin changes\r
+ //This will be PCIE0\r
+ motor_idle_counter = 0;\r
+ PCICR = MASK(PCIE0);\r
+ PCMSK0 = MASK(PCINT2);\r
+}\r
+\r
+ISR(PCINT0_vect) {\r
+ static uint8_t coil_pos, pwm;\r
+\r
+ //if the step pin is high, we advance the motor\r
+ if (READ(E_STEP_PIN)) {\r
+\r
+ //Turn on motors only on first tick to save power I guess\r
+ enable_motors();\r
+\r
+ //Set motor idle counter to zero\r
+ motor_idle_counter = 0;\r
+\r
+ //Advance the coil position\r
+ if (READ(E_DIR_PIN))\r
+ coil_pos++;\r
+ else\r
+ coil_pos--;\r
+\r
+ coil_pos &= 7;\r
+\r
+ //Grab the latest motor power to use\r
+ pwm = motor_pwm;\r
+\r
+ switch(coil_pos) {\r
+ case 0:\r
+ WRITE(H1D, 0);\r
+ WRITE(H2D, 0);\r
+ H1E_PWM = 0;\r
+ H2E_PWM = pwm;\r
+ break;\r
+ case 1:\r
+ WRITE(H1D, 1);\r
+ WRITE(H2D, 0);\r
+ H1E_PWM = pwm;\r
+ H2E_PWM = pwm;\r
+ break;\r
+ case 2:\r
+ WRITE(H1D, 1);\r
+ WRITE(H2D, 0);\r
+ H1E_PWM = pwm;\r
+ H2E_PWM = 0;\r
+ break;\r
+ case 3:\r
+ WRITE(H1D, 1);\r
+ WRITE(H2D, 1);\r
+ H1E_PWM = pwm;\r
+ H2E_PWM = pwm;\r
+ break;\r
+ case 4:\r
+ WRITE(H1D, 1);\r
+ WRITE(H2D, 1);\r
+ H1E_PWM = 0;\r
+ H2E_PWM = pwm;\r
+ break;\r
+ case 5:\r
+ WRITE(H1D, 0);\r
+ WRITE(H2D, 1);\r
+ H1E_PWM = pwm;\r
+ H2E_PWM = pwm;\r
+ break;\r
+ case 6:\r
+ WRITE(H1D, 0);\r
+ WRITE(H2D, 1);\r
+ H1E_PWM = pwm;\r
+ H2E_PWM = 0;\r
+ break;\r
+ case 7:\r
+ WRITE(H1D, 0);\r
+ WRITE(H2D, 0);\r
+ H1E_PWM = pwm;\r
+ H2E_PWM = pwm;\r
+ break;\r
+ }\r
+ }\r
+}\r
+\r
+void init(void) {\r
+ // set up watchdog\r
+ wd_init();\r
+\r
+ // setup analog reading\r
+ analog_init();\r
+\r
+ // set up serial\r
+ intercom_init();\r
+\r
+ // set up inputs and outputs\r
+ io_init();\r
+\r
+ // temp sensor\r
+ temp_init();\r
+\r
+ // heater\r
+ heater_init();\r
+\r
+ // set up extruder motor driver\r
+ motor_init();\r
+\r
+ // set up clock\r
+ timer_init();\r
+\r
+ // enable interrupts\r
+ sei();\r
+\r
+ // reset watchdog\r
+ wd_reset();\r
+}\r
+\r
+uint8_t writebuff[11];\r
+int main (void)\r
+{\r
+ init();\r
+\r
+ enable_heater();\r
+\r
+ // main loop\r
+ for (;;)\r
+ {\r
+ wd_reset();\r
+\r
+ //Read motor PWM\r
+ motor_pwm = analog_read(TRIM_POT_CHANNEL) >> 2;\r
+\r
+ ifclock(CLOCK_FLAG_10MS) {\r
+ // check temperatures and manage heaters\r
+ temp_sensor_tick();\r
+ }\r
+ ifclock(CLOCK_FLAG_250MS) {\r
+ // this is of course bad code, since the interupt routine setting motor_idle_counter to 0 can be run at any time during this code. Worst case, it runs while disable_motors() is halfway in progress\r
+ motor_idle_counter++;\r
+ if (motor_idle_counter > 3)\r
+ disable_motors();\r
+ }\r
+\r
+ // check if we've had a new intercom packet\r
+ if (intercom_flags & FLAG_NEW_RX) {\r
+ intercom_flags &= ~FLAG_NEW_RX;\r
+\r
+ switch (rx.packet.control_word) {\r
+ // M105- read temperatures\r
+ case 105:\r
+ send_temperature(0, temp_get(0));\r
+ temp_set(0, read_temperature(0));\r
+ send_temperature(1, temp_get(1));\r
+ temp_set(1, read_temperature(1));\r
+ start_send();\r
+ break;\r
+ // M130 - set PID P factor\r
+ case 130:\r
+ pid_set_p(rx.packet.control_index, rx.packet.control_data_int32);\r
+ // M131 - set PID I factor\r
+ case 131:\r
+ pid_set_i(rx.packet.control_index, rx.packet.control_data_int32);\r
+ // M132 - set PID D factor\r
+ case 132:\r
+ pid_set_d(rx.packet.control_index, rx.packet.control_data_int32);\r
+ // M133 - set PID I limit\r
+ case 133:\r
+ pid_set_i_limit(rx.packet.control_index, rx.packet.control_data_int32);\r
+ // M134 - save PID values to eeprom\r
+ case 134:\r
+ heater_save_settings();\r
+ break;\r
+ }\r
+ }\r
+
+ if (intercom_flags & FLAG_TX_FINISHED) {
+ WRITE(TX_ENABLE_PIN,0);
+ }\r
+
+ }\r
+}\r