aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoachim Steiger <jsteiger@sysmocom.de>2019-07-26 22:13:51 +0200
committerJoachim Steiger <jsteiger@sysmocom.de>2019-07-30 10:56:51 +0200
commitb1a81c130e7a312daa12c79501c4ea8fc9a97476 (patch)
treec099203574fe586921e11deeb039028795881555
parent298a5ba722c28d815bc29769b453bf061c81851c (diff)
add new board and app for gpio testing on octsimtest board
-rw-r--r--firmware/README.txt2
-rw-r--r--firmware/apps/gpio_test/Makefile3
-rw-r--r--firmware/apps/gpio_test/gpio_test.c10
-rw-r--r--firmware/apps/gpio_test/main.c54
-rw-r--r--firmware/apps/gpio_test/usb_strings.txt10
-rw-r--r--firmware/libboard/octsimtest/include/board.h154
-rw-r--r--firmware/libboard/octsimtest/include/i2c.h28
-rw-r--r--firmware/libboard/octsimtest/include/mcp23017.h23
-rw-r--r--firmware/libboard/octsimtest/source/board_octsimtest.c72
-rw-r--r--firmware/libboard/octsimtest/source/i2c.c225
-rw-r--r--firmware/libboard/octsimtest/source/mcp23017.c106
11 files changed, 687 insertions, 0 deletions
diff --git a/firmware/README.txt b/firmware/README.txt
index fa7f60a..cd04e7a 100644
--- a/firmware/README.txt
+++ b/firmware/README.txt
@@ -24,6 +24,7 @@ Current boards supported are:
* `simtrace`: The good old Osmocom SIMtrace PCB with SAM3 instead of SAM7, open hardware.
* `qmod`: A sysmocom-proprietary quad mPCIe carrier board, publicly available
* `owhw`: An undisclosed sysmocom-internal board, not publicly available
+* `octsimtest`: A sysmocom-proprietary production testing board, not publicly available
= Firmware
@@ -51,6 +52,7 @@ Current applications supported are:
* `cardem`: To provide remote SIM operation capabilities.
* `trace`: To monitor the communication between a SIM card and a phone (corresponds to the functionality provide by the first SIMtrace)
* `triple_play`: To support the three previous functionalities, using USB configurations.
+* `gpio_test`: internal test code
== Memories
diff --git a/firmware/apps/gpio_test/Makefile b/firmware/apps/gpio_test/Makefile
new file mode 100644
index 0000000..b2b4707
--- /dev/null
+++ b/firmware/apps/gpio_test/Makefile
@@ -0,0 +1,3 @@
+C_FILES += $(C_LIBUSB_RT)
+
+C_FILES += gpio_test.c
diff --git a/firmware/apps/gpio_test/gpio_test.c b/firmware/apps/gpio_test/gpio_test.c
new file mode 100644
index 0000000..2ab23e7
--- /dev/null
+++ b/firmware/apps/gpio_test/gpio_test.c
@@ -0,0 +1,10 @@
+#include <stdint.h>
+#include "utils.h"
+#include "chip.h"
+
+
+
+void gpio_test_init(void)
+{
+ printf("FIXME run tests here\n\n");
+}
diff --git a/firmware/apps/gpio_test/main.c b/firmware/apps/gpio_test/main.c
new file mode 100644
index 0000000..8fe68b3
--- /dev/null
+++ b/firmware/apps/gpio_test/main.c
@@ -0,0 +1,54 @@
+
+#include "board.h"
+#include "utils.h"
+#include "osmocom/core/timer.h"
+
+extern void gpio_test_init(void);
+
+/* returns '1' in case we should break any endless loop */
+static void check_exec_dbg_cmd(void)
+{
+ int ch;
+
+ if (!UART_IsRxReady())
+ return;
+
+ ch = UART_GetChar();
+
+ board_exec_dbg_cmd(ch);
+}
+
+
+extern int main(void)
+{
+ led_init();
+ led_blink(LED_RED, BLINK_ALWAYS_ON);
+ led_blink(LED_GREEN, BLINK_ALWAYS_ON);
+
+ /* Enable watchdog for 2000 ms, with no window */
+ WDT_Enable(WDT, WDT_MR_WDRSTEN | WDT_MR_WDDBGHLT | WDT_MR_WDIDLEHLT |
+ (WDT_GetPeriod(2000) << 16) | WDT_GetPeriod(2000));
+
+ PIO_InitializeInterrupts(0);
+
+
+ printf("\n\r\n\r"
+ "=============================================================================\n\r"
+ "GPIO Test firmware " GIT_VERSION " (C) 2019 Sysmocom GmbH\n\r"
+ "=============================================================================\n\r");
+
+ board_main_top();
+
+ TRACE_INFO("starting gpio test...\n\r");
+ gpio_test_init();
+
+ TRACE_INFO("entering main loop...\n\r");
+ while (1) {
+ WDT_Restart(WDT);
+
+ check_exec_dbg_cmd();
+ osmo_timers_prepare();
+ osmo_timers_update();
+ }
+
+}
diff --git a/firmware/apps/gpio_test/usb_strings.txt b/firmware/apps/gpio_test/usb_strings.txt
new file mode 100644
index 0000000..0e797ac
--- /dev/null
+++ b/firmware/apps/gpio_test/usb_strings.txt
@@ -0,0 +1,10 @@
+sysmocom - s.f.m.c. GmbH
+SIMtrace 2 compatible device
+SIMtrace Sniffer
+SIMtrace CCID
+SIMtrace Phone
+SIMtrace MITM
+CardEmulator Modem 1
+CardEmulator Modem 2
+CardEmulator Modem 3
+CardEmulator Modem 4
diff --git a/firmware/libboard/octsimtest/include/board.h b/firmware/libboard/octsimtest/include/board.h
new file mode 100644
index 0000000..2effc02
--- /dev/null
+++ b/firmware/libboard/octsimtest/include/board.h
@@ -0,0 +1,154 @@
+/* octSIMtest with SAM3S board definition
+ *
+ * (C) 2019 by sysmocom -s.f.m.c. GmbH, Author:Joachim Steiger <jsteiger@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
+ */
+#pragma once
+#include "board_common.h"
+#include "simtrace_usb.h"
+
+/* Name of the board */
+#define BOARD_NAME "OCTSIMTEST"
+/* Board definition */
+#define octsimtest
+
+/** oscillator used as main clock source (in Hz) */
+#define BOARD_MAINOSC 18432000
+/** desired main clock frequency (in Hz, based on BOARD_MAINOSC) */
+#define BOARD_MCK 58982400 // 18.432 * 16 / 5
+
+/** Pin configuration **/
+/* Button to force bootloader start (shorted to ground when pressed */
+#define PIN_BOOTLOADER_SW {PIO_PA5, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP}
+
+//FIXME SIM_PWEN_PIN collides with PA5/bootloader_sw on octsimtest
+/* Enable powering the card using the second 3.3 V output of the LDO (active high) */
+#define SIM_PWEN_PIN {PIO_PA12, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+/* Enable powering the SIM card */
+#define PWR_PINS SIM_PWEN_PIN
+
+// FIXME PA8 is 32khz xtal on octsimtest
+/* Card presence pin */
+#define SW_SIM PIO_PA11
+/* Pull card presence pin high (shorted to ground in card slot when card is present) */
+#define SMARTCARD_CONNECT_PIN {SW_SIM, PIOA, ID_PIOA, PIO_INPUT, PIO_PULLUP | PIO_DEBOUNCE | PIO_DEGLITCH | PIO_IT_EDGE }
+
+/** Smart card connection **/
+//FIXME
+/* Card RST reset signal input (active low; RST_SIM in schematic) */
+#define PIN_SIM_RST {PIO_PA13, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+/* Card I/O data signal input/output (I/O_SIM in schematic) */
+#define PIN_SIM_IO {PIO_PA6A_TXD0, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+/* Card CLK clock input (CLK_SIM in schematic) */
+#define PIN_SIM_CLK {PIO_PA2B_SCK0, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
+/* Pin to measure card I/O timing (to start measuring the ETU on I/O activity; connected I/O_SIM in schematic) */
+#define PIN_SIM_IO_INPUT {PIO_PA1B_TIOB0, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
+//FIXME PIO_PA4B_TCLK0 PA4 is LED on octsimtest
+/* Pin used as clock input (to measure the ETU duration; connected to CLK_SIM in schematic) */
+#define PIN_SIM_CLK_INPUT {PIO_PA14, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
+/* Pins used to measure ETU timing (using timer counter) */
+#define PINS_TC PIN_SIM_IO_INPUT, PIN_SIM_CLK_INPUT
+
+/** Phone connection **/
+/* Phone USIM slot 1 VCC pin (VCC_PHONE in schematic) */
+#define PIN_USIM1_VCC {PIO_PA25, PIOA, ID_PIOA, PIO_INPUT, PIO_DEFAULT}
+/* Phone USIM slot 1 RST pin (active low; RST_PHONE in schematic) */
+#define PIN_USIM1_nRST {PIO_PA24, PIOA, ID_PIOA, PIO_INPUT, PIO_IT_RISE_EDGE | PIO_DEGLITCH }
+/* Phone I/O data signal input/output (I/O_PHONE in schematic) */
+#define PIN_PHONE_IO {PIO_PA22A_TXD1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+/* Phone CLK clock input (CLK_PHONE in schematic) */
+#define PIN_PHONE_CLK {PIO_PA23A_SCK1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+/* Pin used for phone USIM slot 1 communication */
+#define PINS_USIM1 PIN_PHONE_IO, PIN_PHONE_CLK, PIN_PHONE_CLK_INPUT, PIN_USIM1_VCC, PIN_PHONE_IO_INPUT, PIN_USIM1_nRST
+/* Phone I/O data signal input/output (unused USART RX input; connected to I/O_PHONE in schematic) */
+#define PIN_PHONE_IO_INPUT {PIO_PA21A_RXD1, PIOA, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+/* Pin used as clock input (to measure the ETU duration; connected to CLK_PHONE in schematic) */
+#define PIN_PHONE_CLK_INPUT {PIO_PA29B_TCLK2, PIOA, ID_PIOA, PIO_PERIPH_B, PIO_DEFAULT}
+
+/** Default pin configuration **/
+/* Disconnect VPP, CLK, and RST lines between card and phone using bus switch (high sets bus switch to high-impedance) */
+#define PIN_SC_SW_DEFAULT {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+/* Disconnect I/O line between card and phone using bus switch (high sets bus switch to high-impedance) */
+#define PIN_IO_SW_DEFAULT {PIO_PA19, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+/* Disconnect all lines (VPP, CLK, RST, and I/O) between card and phone */
+#define PINS_BUS_DEFAULT PIN_SC_SW_DEFAULT, PIN_IO_SW_DEFAULT
+
+/** Sniffer configuration **/
+/* Connect VPP, CLK, and RST lines between card and phone using bus switch (low connects signals on bus switch) */
+#define PIN_SC_SW_SNIFF {PIO_PA20, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+/* Connect I/O line between card and phone using bus switch (low connects signals on bus switch) */
+#define PIN_IO_SW_SNIFF {PIO_PA19, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+/* Connect all lines (VPP, CLK, RST, and I/O) between card and phone */
+#define PINS_BUS_SNIFF PIN_SC_SW_SNIFF, PIN_IO_SW_SNIFF
+/* Card RST reset signal input (use as input since the phone will drive it) */
+#define PIN_SIM_RST_SNIFF {PIO_PA7, PIOA, ID_PIOA, PIO_INPUT, PIO_DEGLITCH | PIO_IT_EDGE}
+/* Pins used to sniff phone-card communication */
+#define PINS_SIM_SNIFF PIN_SIM_IO, PIN_SIM_CLK, PIN_SIM_RST_SNIFF
+/* Disable power converter 4.5-6V to 3.3V (active high) */
+#define PIN_SIM_PWEN_SNIFF {SIM_PWEN, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+/* Enable power switch to forward VCC_PHONE to VCC_SIM (active high) */
+#define PIN_VCC_FWD_SNIFF {VCC_FWD, PIOA, ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT}
+/* Use phone VCC to power card */
+#define PINS_PWR_SNIFF PIN_SIM_PWEN_SNIFF, PIN_VCC_FWD_SNIFF
+
+/** CCID configuration */
+/* Card RST reset signal input (active low; RST_SIM in schematic) */
+#define PIN_ISO7816_RSTMC {PIO_PA7, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+/* ISO7816-communication related pins */
+#define PINS_ISO7816 PIN_SIM_IO, PIN_SIM_CLK, PIN_ISO7816_RSTMC // SIM_PWEN_PIN, PIN_SIM_IO2, PIN_SIM_CLK2
+
+/** External SPI flash interface **/
+/* SPI MISO pin definition */
+#define PIN_SPI_MISO {PIO_PA12A_MISO, PIOA, PIOA, PIO_PERIPH_A, PIO_PULLUP}
+/* SPI MOSI pin definition */
+#define PIN_SPI_MOSI {PIO_PA13A_MOSI, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+/* SPI SCK pin definition */
+#define PIN_SPI_SCK {PIO_PA14A_SPCK, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+/* SPI pins definition. Contains MISO, MOSI & SCK */
+#define PINS_SPI PIN_SPI_MISO, PIN_SPI_MOSI, PIN_SPI_SCK
+/* SPI chip select 0 pin definition */
+#define PIN_SPI_NPCS0 {PIO_PA11A_NPCS0, PIOA, PIOA, PIO_PERIPH_A, PIO_DEFAULT}
+/* SPI flash write protect pin (active low, pulled low) */
+#define PIN_SPI_WP {PA15, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+
+/** Pin configuration to control USB pull-up on D+
+ * @details the USB pull-up on D+ is enable by default on the board but can be disabled by setting PA16 high
+ */
+#define PIN_USB_PULLUP {PIO_PA16, PIOA, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT}
+
+/** USB definitions */
+/* OpenMoko SIMtrace 2 USB vendor ID */
+#define BOARD_USB_VENDOR_ID USB_VENDOR_OPENMOKO
+/* OpenMoko SIMtrace 2 USB product ID (main application/runtime mode) */
+#define BOARD_USB_PRODUCT_ID USB_PRODUCT_SIMTRACE2
+/* OpenMoko SIMtrace 2 DFU USB product ID (DFU bootloader/DFU mode) */
+#define BOARD_DFU_USB_PRODUCT_ID USB_PRODUCT_SIMTRACE2_DFU
+/* USB release number (bcdDevice, shown as 0.00) */
+#define BOARD_USB_RELEASE 0x000
+/* Indicate SIMtrace is bus power in USB attributes */
+#define BOARD_USB_BMATTRIBUTES USBConfigurationDescriptor_BUSPOWERED_NORWAKEUP
+
+/** Supported modes */
+/* SIMtrace board supports sniffer mode */
+//#define HAVE_SNIFFER
+/* SIMtrace board supports CCID mode */
+//#define HAVE_CCID
+/* SIMtrace board supports card emulation mode */
+//#define HAVE_CARDEM
+/* SIMtrace board supports man-in-the-middle mode */
+//#define HAVE_MITM
+/* octsimtest board supports gpio_test mode */
+#define HAVE_GPIO_TEST
diff --git a/firmware/libboard/octsimtest/include/i2c.h b/firmware/libboard/octsimtest/include/i2c.h
new file mode 100644
index 0000000..5a8c908
--- /dev/null
+++ b/firmware/libboard/octsimtest/include/i2c.h
@@ -0,0 +1,28 @@
+/* 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
+ */
+#pragma once
+
+#include <stdbool.h>
+
+void i2c_pin_init(void);
+
+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 eeprom_write_byte(uint8_t slave, uint8_t addr, uint8_t byte);
+int eeprom_read_byte(uint8_t slave, uint8_t addr);
diff --git a/firmware/libboard/octsimtest/include/mcp23017.h b/firmware/libboard/octsimtest/include/mcp23017.h
new file mode 100644
index 0000000..dea6285
--- /dev/null
+++ b/firmware/libboard/octsimtest/include/mcp23017.h
@@ -0,0 +1,23 @@
+/* mcp23017 i2c gpio expander 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
+ */
+#pragma once
+
+#define MCP23017_ADDRESS 0x20
+
+int mcp23017_init(uint8_t slave);
+//int mcp23017_write_byte(uint8_t slave, uint8_t addr, uint8_t byte);
+//int mcp23017_read_byte(uint8_t slave, uint8_t addr);
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;
+}
+