Added i2c slave interface
authorJoseph Coffland <joseph@cauldrondevelopment.com>
Wed, 27 Jul 2016 22:46:19 +0000 (15:46 -0700)
committerJoseph Coffland <joseph@cauldrondevelopment.com>
Wed, 27 Jul 2016 22:46:19 +0000 (15:46 -0700)
src/command.c
src/command.def
src/config.h
src/i2c.c [new file with mode: 0644]
src/i2c.h [new file with mode: 0644]
src/main.c
src/plan/command.c
src/switch.c

index 050d1c954e42b2ce7826beb7ba96fc5ec5264dc2..4e6ced9ad2eb987dfc6b7f5fb262b04282f7113d 100644 (file)
@@ -47,6 +47,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
+#include <stdlib.h>
 
 
 // Command forward declarations
@@ -286,3 +287,12 @@ uint8_t command_messages(int argc, char *argv[]) {
   status_help();
   return 0;
 }
+
+
+uint8_t command_sync(int argc, char *argv[]) {
+  char *end = 0;
+  uint32_t x = strtoul(argv[1], &end, 0);
+
+  if (end) printf_P(PSTR("\n{\"sync\": %lu}\n"), x);
+  return 0;
+}
index 03f5dcadefb5c857fa2080b3e5cf0faf3fa3a139..7f451b329338fe3285d7c724acbe81e9f04bfb0c 100644 (file)
@@ -37,3 +37,4 @@ CMD(jog,          1, 4, "Jog")
 CMD(mreset,       0, 1, "Reset motor")
 CMD(calibrate,    0, 0, "Calibrate motors")
 CMD(messages,     0, 0, "Dump all possible status messages")
+CMD(sync,         1, 1, "Synchronize with queue processing")
index e737bd7ad86e5e7f15ba294dca8027aab7416299..085eaf4714693de4b95c04aab469863bb03bc0bd 100644 (file)
@@ -55,8 +55,8 @@ enum {
   SPIN_ENABLE_PIN,
   BOOT_PIN,
 
-  READY_PIN = PORT_C << 3,
-  PROBE_PIN,
+  SDA_PIN = PORT_C << 3,
+  SCL_PIN,
   SERIAL_RX_PIN,
   SERIAL_TX_PIN,
   SERIAL_CTS_PIN,
@@ -103,7 +103,7 @@ enum {
 #define AXES                     6 // number of axes
 #define MOTORS                   4 // number of motors on the board
 #define COORDS                   6 // number of supported coordinate systems
-#define SWITCHES                10 // number of supported limit switches
+#define SWITCHES                 9 // number of supported limit switches
 #define PWMS                     2 // number of supported PWM channels
 
 
diff --git a/src/i2c.c b/src/i2c.c
new file mode 100644 (file)
index 0000000..4670054
--- /dev/null
+++ b/src/i2c.c
@@ -0,0 +1,94 @@
+/******************************************************************************\
+
+                This file is part of the Buildbotics firmware.
+
+                  Copyright (c) 2015 - 2016 Buildbotics LLC
+                  Copyright (c) 2010 - 2013 Alden S. Hart Jr.
+                            All rights reserved.
+
+     This file ("the software") is free software: you can redistribute it
+     and/or modify it under the terms of the GNU General Public License,
+      version 2 as published by the Free Software Foundation. You should
+      have received a copy of the GNU General Public License, version 2
+     along with the software. If not, see <http://www.gnu.org/licenses/>.
+
+     The software 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
+               Lesser General Public License for more details.
+\
+       You should have received a copy of the GNU Lesser General Public
+                License along with the software.  If not, see
+                       <http://www.gnu.org/licenses/>.
+
+                For information regarding this software email:
+                  "Joseph Coffland" <joseph@buildbotics.com>
+
+\******************************************************************************/
+
+#include "i2c.h"
+#include "config.h"
+
+#include <avr/interrupt.h>
+
+#include <stdbool.h>
+
+
+typedef struct {
+  spi_cb_t cb;
+  uint8_t data[I2C_MAX_DATA];
+  uint8_t length;
+} spi_t;
+
+static spi_t spi = {0};
+
+
+ISR(I2C_ISR) {
+  static bool first = false;
+  uint8_t status = I2C_DEV.SLAVE.STATUS;
+
+  // Error or collision
+  if (status & (TWI_SLAVE_BUSERR_bm | TWI_SLAVE_COLL_bm)) return; // Ignore
+
+  // Address match
+  else if ((status & TWI_SLAVE_APIF_bm) && (status & TWI_SLAVE_AP_bm)) {
+    I2C_DEV.SLAVE.CTRLB = TWI_SLAVE_CMD_RESPONSE_gc; // ACK address byte
+    first = true;
+    spi.length = 0;
+
+  } else if (status & TWI_SLAVE_APIF_bm) { // STOP interrupt
+    I2C_DEV.SLAVE.STATUS = TWI_SLAVE_APIF_bm; // Clear interrupt flag
+    if (spi.cb) spi.cb(spi.data, spi.length);
+
+  } else if (status & TWI_SLAVE_DIF_bm) { // Data interrupt
+    if (status & TWI_SLAVE_DIR_bm) { // Write
+      // Check if master ACKed last byte sent
+      if (status & TWI_SLAVE_RXACK_bm && !first)
+        I2C_DEV.SLAVE.CTRLB = TWI_SLAVE_CMD_COMPTRANS_gc; // End transaction
+
+      else {
+        I2C_DEV.SLAVE.DATA = 0; // Send some data
+        I2C_DEV.SLAVE.CTRLB = TWI_SLAVE_CMD_RESPONSE_gc; // Continue transaction
+      }
+
+      first = false;
+
+    } else { // Read
+      uint8_t data = I2C_DEV.SLAVE.DATA;
+      if (spi.length < I2C_MAX_DATA) spi.data[spi.length++] = data;
+
+      // ACK and continue transaction
+      I2C_DEV.SLAVE.CTRLB = TWI_SLAVE_CMD_RESPONSE_gc;
+    }
+  }
+}
+
+
+void i2c_init() {
+  I2C_DEV.SLAVE.CTRLA = TWI_SLAVE_INTLVL_HI_gc | TWI_SLAVE_DIEN_bm |
+    TWI_SLAVE_ENABLE_bm | TWI_SLAVE_APIEN_bm | TWI_SLAVE_PIEN_bm;
+  I2C_DEV.SLAVE.ADDR = I2C_ADDR << 1;
+}
+
+
+void i2c_set_callback(spi_cb_t cb) {spi.cb = cb;}
diff --git a/src/i2c.h b/src/i2c.h
new file mode 100644 (file)
index 0000000..53f7d6d
--- /dev/null
+++ b/src/i2c.h
@@ -0,0 +1,43 @@
+/******************************************************************************\
+
+                This file is part of the Buildbotics firmware.
+
+                  Copyright (c) 2015 - 2016 Buildbotics LLC
+                  Copyright (c) 2010 - 2013 Alden S. Hart Jr.
+                            All rights reserved.
+
+     This file ("the software") is free software: you can redistribute it
+     and/or modify it under the terms of the GNU General Public License,
+      version 2 as published by the Free Software Foundation. You should
+      have received a copy of the GNU General Public License, version 2
+     along with the software. If not, see <http://www.gnu.org/licenses/>.
+
+     The software 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
+               Lesser General Public License for more details.
+
+       You should have received a copy of the GNU Lesser General Public
+                License along with the software.  If not, see
+                       <http://www.gnu.org/licenses/>.
+
+                For information regarding this software email:
+                  "Joseph Coffland" <joseph@buildbotics.com>
+
+\******************************************************************************/
+
+#pragma once
+
+#include <stdint.h>
+
+
+#define I2C_DEV TWIC
+#define I2C_ISR TWIC_TWIS_vect
+#define I2C_ADDR 0x2b
+#define I2C_MAX_DATA 8
+
+
+typedef void (*spi_cb_t)(uint8_t *data, uint8_t length);
+
+void i2c_init();
+void i2c_set_callback(spi_cb_t cb);
index d759cbb39dedde5b857801db50bcf571d1b0cda7..f68472d379853ec15e1fe57f7d540ea3bfe4ce85 100644 (file)
 #include "estop.h"
 #include "probing.h"
 #include "homing.h"
+#include "i2c.h"
 
 #include "plan/planner.h"
 #include "plan/arc.h"
 #include "plan/feedhold.h"
 
-#include <avr/interrupt.h>
 #include <avr/pgmspace.h>
 #include <avr/wdt.h>
 
 int main() {
   //wdt_enable(WDTO_250MS);
 
-  cli(); // disable interrupts
+  // Init
+  cli();                          // disable interrupts
 
   hardware_init();                // hardware setup - must be first
   usart_init();                   // serial port
+  i2c_init();                     // i2c port
   tmc2660_init();                 // motor drivers
   stepper_init();                 // steppers
   motor_init();                   // motors
   switch_init();                  // switches
   planner_init();                 // motion planning
-  machine_init();       // gcode machine
+  machine_init();                 // gcode machine
   vars_init();                    // configuration variables
   estop_init();                   // emergency stop handler
 
-  sei(); // enable interrupts
+  sei();                          // enable interrupts
 
-  fprintf_P(stderr, PSTR("\n{\"firmware\": \"Buildbotics AVR\", "
+  // Splash
+  fprintf_P(stdout, PSTR("\n{\"firmware\": \"Buildbotics AVR\", "
                          "\"version\": \"" VERSION "\"}\n"));
 
-  // main loop
+  // Main loop
   while (true) {
-    hw_reset_handler();                        // handle hard reset requests
-    mach_feedhold_callback();                    // feedhold state machine
-    mach_arc_callback();                         // arc generation runs
-    mach_homing_callback();                      // G28.2 continuation
-    mach_probe_callback();                       // G38.2 continuation
-    command_callback();                        // process next command
-    report_callback();                         // report changes
+    hw_reset_handler();           // handle hard reset requests
+    mach_feedhold_callback();     // feedhold state machine
+    mach_arc_callback();          // arc generation runs
+    mach_homing_callback();       // G28.2 continuation
+    mach_probe_callback();        // G38.2 continuation
+    command_callback();           // process next command
+    report_callback();            // report changes
     wdt_reset();
   }
 
index 2209f9ac210e329b0564fb35b147d01e21a53b7f..c1227c11ba876bd57294c74a00a59a198ab5ba54 100644 (file)
@@ -70,7 +70,7 @@ void mp_queue_command(mach_exec_t mach_exec, float *value, float *flag) {
 
   bf->move_type = MOVE_TYPE_COMMAND;
   bf->bf_func = _exec_command;    // callback to planner queue exec function
-  bf->mach_func = mach_exec;          // callback to machine exec function
+  bf->mach_func = mach_exec;      // callback to machine exec function
 
   // Store values and flags in planner buffer
   for (int axis = 0; axis < AXES; axis++) {
index c9279c2a03185ca69f084362577d8a1c10de1235..cf56ba7b1b875666624c06c5b078a657d3fec0ae 100644 (file)
@@ -83,7 +83,7 @@ static switch_t switches[SWITCHES] = {
   {.pin = MIN_A_PIN, .type = SW_NORMALLY_OPEN},
   {.pin = MAX_A_PIN, .type = SW_NORMALLY_OPEN},
   {.pin = ESTOP_PIN, .type = SW_NORMALLY_OPEN},
-  {.pin = PROBE_PIN, .type = SW_NORMALLY_OPEN},
+  //  {.pin = PROBE_PIN, .type = SW_NORMALLY_OPEN},
 };