add new board and app for gpio testing on octsimtest board
Change-Id: I01243044002f51b34e8dc12c1b1f565bbf1740a2
diff --git a/firmware/libboard/octsimtest/source/board_octsimtest.c b/firmware/libboard/octsimtest/source/board_octsimtest.c
new file mode 100644
index 0000000..2772015
--- /dev/null
+++ b/firmware/libboard/octsimtest/source/board_octsimtest.c
@@ -0,0 +1,72 @@
+/* SIMtrace with SAM3S specific application code
+ *
+ * (C) 2017 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2018 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ */
+#include "board.h"
+#include "simtrace.h"
+#include "utils.h"
+#include "sim_switch.h"
+#include <osmocom/core/timer.h>
+#include "usb_buf.h"
+#include "i2c.h"
+#include "mcp23017.h"
+
+void board_exec_dbg_cmd(int ch)
+{
+ switch (ch) {
+ case '?':
+ printf("\t?\thelp\n\r");
+ printf("\tR\treset SAM3\n\r");
+ break;
+ case 'R':
+ printf("Asking NVIC to reset us\n\r");
+ USBD_Disconnect();
+ NVIC_SystemReset();
+ break;
+ default:
+ printf("Unknown command '%c'\n\r", ch);
+ break;
+ }
+}
+
+void board_main_top(void)
+{
+#ifndef APPLICATION_dfu
+ usb_buf_init();
+
+ i2c_pin_init();
+ mcp23017_init(MCP23017_ADDRESS);
+ /* Initialize checking for card insert/remove events */
+ //card_present_init();
+#endif
+}
+
+int board_override_enter_dfu(void)
+{
+ const Pin bl_sw_pin = PIN_BOOTLOADER_SW;
+
+ PIO_Configure(&bl_sw_pin, 1);
+
+ /* Enter DFU bootloader in case the respective button is pressed */
+ if (PIO_Get(&bl_sw_pin) == 0) {
+ /* do not print to early since the console is not initialized yet */
+ //printf("BOOTLOADER switch pressed -> Force DFU\n\r");
+ return 1;
+ } else
+ return 0;
+}
diff --git a/firmware/libboard/octsimtest/source/i2c.c b/firmware/libboard/octsimtest/source/i2c.c
new file mode 100644
index 0000000..a708704
--- /dev/null
+++ b/firmware/libboard/octsimtest/source/i2c.c
@@ -0,0 +1,225 @@
+/* I2C EEPROM memory read and write utilities
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
+ */
+#include "board.h"
+#include <stdbool.h>
+
+/* Low-Level I2C Routines */
+
+static const Pin pin_sda = {PIO_PA30, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_OPENDRAIN };
+static const Pin pin_sda_in = {PIO_PA30, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT };
+static const Pin pin_scl = {PIO_PA31, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_OPENDRAIN };
+
+static void i2c_delay()
+{
+ volatile int v;
+ int i;
+
+ /* 100 cycles results in SCL peak length of 44us, so it's about
+ * 440ns per cycle here */
+ for (i = 0; i < 14; i++) {
+ v = 0;
+ }
+}
+
+void i2c_pin_init(void)
+{
+ PIO_Configure(&pin_scl, PIO_LISTSIZE(pin_scl));
+ PIO_Configure(&pin_sda, PIO_LISTSIZE(pin_sda));
+}
+
+static void set_scl(void)
+{
+ PIO_Set(&pin_scl);
+ i2c_delay();
+}
+
+static void set_sda(void)
+{
+ PIO_Set(&pin_sda);
+ i2c_delay();
+}
+
+static void clear_scl(void)
+{
+ PIO_Clear(&pin_scl);
+ i2c_delay();
+}
+
+static void clear_sda(void)
+{
+ PIO_Clear(&pin_sda);
+ i2c_delay();
+}
+
+static bool read_sda(void)
+{
+ bool ret;
+
+ PIO_Configure(&pin_sda_in, PIO_LISTSIZE(pin_sda_in));
+ if (PIO_Get(&pin_sda_in))
+ ret = true;
+ else
+ ret = false;
+ PIO_Configure(&pin_sda, PIO_LISTSIZE(pin_sda));
+
+ return ret;
+}
+
+/* Core I2C Routines */
+
+static bool i2c_started = false;
+
+static void i2c_start_cond(void)
+{
+ if (i2c_started) {
+ set_sda();
+ set_scl();
+ }
+
+ clear_sda();
+ i2c_delay();
+ clear_scl();
+ i2c_started = true;
+}
+
+static void i2c_stop_cond(void)
+{
+ clear_sda();
+ set_scl();
+ set_sda();
+ i2c_delay();
+ i2c_started = false;
+}
+
+static void i2c_write_bit(bool bit)
+{
+ if (bit)
+ set_sda();
+ else
+ clear_sda();
+ i2c_delay(); // ?
+ set_scl();
+ clear_scl();
+}
+
+static bool i2c_read_bit(void)
+{
+ bool bit;
+
+ set_sda();
+ set_scl();
+ bit = read_sda();
+ clear_scl();
+
+ return bit;
+}
+
+bool i2c_write_byte(bool send_start, bool send_stop, uint8_t byte)
+{
+ uint8_t bit;
+ bool nack;
+
+ if (send_start)
+ i2c_start_cond();
+
+ for (bit = 0; bit < 8; bit++) {
+ i2c_write_bit((byte & 0x80) != 0);
+ byte <<= 1;
+ }
+
+ nack = i2c_read_bit();
+
+ if (send_stop)
+ i2c_stop_cond();
+
+ return nack;
+}
+
+uint8_t i2c_read_byte(bool nack, bool send_stop)
+{
+ uint8_t byte = 0;
+ uint8_t bit;
+
+ for (bit = 0; bit < 8; bit++) {
+ byte = (byte << 1) | i2c_read_bit();
+ }
+
+ i2c_write_bit(nack);
+
+ if (send_stop)
+ i2c_stop_cond();
+
+ return byte;
+}
+
+
+/* EEPROM related code */
+
+int eeprom_write_byte(uint8_t slave, uint8_t addr, uint8_t byte)
+{
+ bool nack;
+
+ WDT_Restart(WDT);
+
+ /* Write slave address */
+ nack = i2c_write_byte(true, false, slave << 1);
+ if (nack)
+ goto out_stop;
+ nack = i2c_write_byte(false, false, addr);
+ if (nack)
+ goto out_stop;
+ nack = i2c_write_byte(false, true, byte);
+ if (nack)
+ goto out_stop;
+ /* Wait tWR time to ensure EEPROM is writing correctly (tWR = 5 ms for AT24C02) */
+ mdelay(5);
+
+out_stop:
+ i2c_stop_cond();
+ if (nack)
+ return -1;
+ else
+ return 0;
+}
+
+int eeprom_read_byte(uint8_t slave, uint8_t addr)
+{
+ bool nack;
+
+ WDT_Restart(WDT);
+
+ /* dummy write cycle */
+ nack = i2c_write_byte(true, false, slave << 1);
+ if (nack)
+ goto out_stop;
+ nack = i2c_write_byte(false, false, addr);
+ if (nack)
+ goto out_stop;
+ /* Re-start with read */
+ nack = i2c_write_byte(true, false, (slave << 1) | 1);
+ if (nack)
+ goto out_stop;
+
+ return i2c_read_byte(true, true);
+
+out_stop:
+ i2c_stop_cond();
+ if (nack)
+ return -1;
+ else
+ return 0;
+}
diff --git a/firmware/libboard/octsimtest/source/mcp23017.c b/firmware/libboard/octsimtest/source/mcp23017.c
new file mode 100644
index 0000000..63390b4
--- /dev/null
+++ b/firmware/libboard/octsimtest/source/mcp23017.c
@@ -0,0 +1,106 @@
+#include "board.h"
+#include <stdbool.h>
+#include "i2c.h"
+#include "mcp23017.h"
+
+
+//defines from https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library/blob/master/Adafruit_MCP23017.h under BSD license
+
+// registers
+#define MCP23017_IODIRA 0x00
+#define MCP23017_IPOLA 0x02
+#define MCP23017_GPINTENA 0x04
+#define MCP23017_DEFVALA 0x06
+#define MCP23017_INTCONA 0x08
+#define MCP23017_IOCONA 0x0A
+#define MCP23017_GPPUA 0x0C
+#define MCP23017_INTFA 0x0E
+#define MCP23017_INTCAPA 0x10
+#define MCP23017_GPIOA 0x12
+#define MCP23017_OLATA 0x14
+
+
+#define MCP23017_IODIRB 0x01
+#define MCP23017_IPOLB 0x03
+#define MCP23017_GPINTENB 0x05
+#define MCP23017_DEFVALB 0x07
+#define MCP23017_INTCONB 0x09
+#define MCP23017_IOCONB 0x0B
+#define MCP23017_GPPUB 0x0D
+#define MCP23017_INTFB 0x0F
+#define MCP23017_INTCAPB 0x11
+#define MCP23017_GPIOB 0x13
+#define MCP23017_OLATB 0x15
+
+#define MCP23017_INT_ERR 255
+
+
+//bool i2c_write_byte(bool send_start, bool send_stop, uint8_t byte)
+//uint8_t i2c_read_byte(bool nack, bool send_stop)
+//static void i2c_stop_cond(void)
+
+int mcp23017_write_byte(uint8_t slave, uint8_t addr, uint8_t byte)
+{
+ bool nack;
+
+ WDT_Restart(WDT);
+
+// Write slave address
+ nack = i2c_write_byte(true, false, slave << 1);
+ if (nack)
+ goto out_stop;
+ nack = i2c_write_byte(false, false, addr);
+ if (nack)
+ goto out_stop;
+ nack = i2c_write_byte(false, true, byte);
+ if (nack)
+ goto out_stop;
+
+out_stop:
+ i2c_stop_cond();
+ if (nack)
+ return -1;
+ else
+ return 0;
+}
+
+int mcp23017_read_byte(uint8_t slave, uint8_t addr)
+{
+ bool nack;
+
+ WDT_Restart(WDT);
+
+ // dummy write cycle
+ nack = i2c_write_byte(true, false, slave << 1);
+ if (nack)
+ goto out_stop;
+ nack = i2c_write_byte(false, false, addr);
+ if (nack)
+ goto out_stop;
+ // Re-start with read
+ nack = i2c_write_byte(true, false, (slave << 1) | 1);
+ if (nack)
+ goto out_stop;
+
+ return i2c_read_byte(true, true);
+
+out_stop:
+ i2c_stop_cond();
+ if (nack)
+ return -1;
+ else
+ return 0;
+}
+
+int mcp23017_init(uint8_t slave)
+{
+ printf("mcp23017_init\n");
+ // all gpio input
+ if (mcp23017_write_byte(slave, MCP23017_IODIRA, 0xff))
+ return false;
+ if (mcp23017_write_byte(slave, MCP23017_IODIRB, 0xff))
+ return false;
+ printf("mcp23017 found\n");
+ return true;
+}
+