reprap teacup firmware config
[svn42.git] / reprap_mendel_prusa / teacup_firmware / extruder / extruder.c
diff --git a/reprap_mendel_prusa/teacup_firmware/extruder/extruder.c b/reprap_mendel_prusa/teacup_firmware/extruder/extruder.c
new file mode 100644 (file)
index 0000000..b9a5f50
--- /dev/null
@@ -0,0 +1,250 @@
+#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