From b1a81c130e7a312daa12c79501c4ea8fc9a97476 Mon Sep 17 00:00:00 2001 From: Joachim Steiger Date: Fri, 26 Jul 2019 22:13:51 +0200 Subject: add new board and app for gpio testing on octsimtest board Change-Id: I01243044002f51b34e8dc12c1b1f565bbf1740a2 --- firmware/README.txt | 2 + firmware/apps/gpio_test/Makefile | 3 + firmware/apps/gpio_test/gpio_test.c | 10 + firmware/apps/gpio_test/main.c | 54 +++++ firmware/apps/gpio_test/usb_strings.txt | 10 + firmware/libboard/octsimtest/include/board.h | 154 ++++++++++++++ firmware/libboard/octsimtest/include/i2c.h | 28 +++ firmware/libboard/octsimtest/include/mcp23017.h | 23 +++ .../libboard/octsimtest/source/board_octsimtest.c | 72 +++++++ firmware/libboard/octsimtest/source/i2c.c | 225 +++++++++++++++++++++ firmware/libboard/octsimtest/source/mcp23017.c | 106 ++++++++++ 11 files changed, 687 insertions(+) create mode 100644 firmware/apps/gpio_test/Makefile create mode 100644 firmware/apps/gpio_test/gpio_test.c create mode 100644 firmware/apps/gpio_test/main.c create mode 100644 firmware/apps/gpio_test/usb_strings.txt create mode 100644 firmware/libboard/octsimtest/include/board.h create mode 100644 firmware/libboard/octsimtest/include/i2c.h create mode 100644 firmware/libboard/octsimtest/include/mcp23017.h create mode 100644 firmware/libboard/octsimtest/source/board_octsimtest.c create mode 100644 firmware/libboard/octsimtest/source/i2c.c create mode 100644 firmware/libboard/octsimtest/source/mcp23017.c (limited to 'firmware') 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 +#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 + * + * 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 + +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 + * (C) 2018 by sysmocom -s.f.m.c. GmbH, Author: Kevin Redon + * + * 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 +#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 + +/* 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 +#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; +} + -- cgit v1.2.3