From 3679dc0601220ee4ac897d7e3af4cb59b545e984 Mon Sep 17 00:00:00 2001 From: Baldanos Date: Thu, 14 Apr 2016 22:12:05 +0200 Subject: [PATCH] Initial BBIO 2-Wire support (#47) --- hydrabus/hydrabus.mk | 3 +- hydrabus/hydrabus_bbio.c | 3 +- hydrabus/hydrabus_bbio.h | 22 +++++ hydrabus/hydrabus_bbio_twowire.c | 146 +++++++++++++++++++++++++++++++ hydrabus/hydrabus_bbio_twowire.h | 20 +++++ hydrabus/hydrabus_mode_twowire.c | 45 +++++----- hydrabus/hydrabus_mode_twowire.h | 16 +++- 7 files changed, 231 insertions(+), 24 deletions(-) create mode 100644 hydrabus/hydrabus_bbio_twowire.c create mode 100644 hydrabus/hydrabus_bbio_twowire.h diff --git a/hydrabus/hydrabus.mk b/hydrabus/hydrabus.mk index cf716315..0975fba3 100644 --- a/hydrabus/hydrabus.mk +++ b/hydrabus/hydrabus.mk @@ -19,7 +19,8 @@ HYDRABUSSRC = hydrabus/hydrabus.c \ hydrabus/hydrabus_bbio_pin.c \ hydrabus/hydrabus_bbio_can.c \ hydrabus/hydrabus_bbio_uart.c \ - hydrabus/hydrabus_bbio_i2c.c + hydrabus/hydrabus_bbio_i2c.c \ + hydrabus/hydrabus_bbio_twowire.c # Required include directories HYDRABUSINC = ./hydrabus diff --git a/hydrabus/hydrabus_bbio.c b/hydrabus/hydrabus_bbio.c index 78a68646..ae8ea464 100644 --- a/hydrabus/hydrabus_bbio.c +++ b/hydrabus/hydrabus_bbio.c @@ -31,6 +31,7 @@ #include "hydrabus_bbio_can.h" #include "hydrabus_bbio_uart.h" #include "hydrabus_bbio_i2c.h" +#include "hydrabus_bbio_twowire.h" int cmd_bbio(t_hydra_console *con) { @@ -58,7 +59,7 @@ int cmd_bbio(t_hydra_console *con) break; case BBIO_RAWWIRE: cprint(con, "RAW1", 4); - //TODO + bbio_mode_twowire(con); break; case BBIO_JTAG: cprint(con, "OCD1", 4); diff --git a/hydrabus/hydrabus_bbio.h b/hydrabus/hydrabus_bbio.h index ea5c8493..4c19ca0c 100644 --- a/hydrabus/hydrabus_bbio.h +++ b/hydrabus/hydrabus_bbio.h @@ -102,4 +102,26 @@ #define BBIO_UART_SET_SPEED 0b01100000 #define BBIO_UART_CONFIG 0b10000000 +/* + * 2-Wire-specific commands + */ +#define BBIO_2WIRE_I2C_START 0b00000010 +#define BBIO_2WIRE_I2C_STOP 0b00000011 +#define BBIO_2WIRE_CS_LOW 0b00000100 +#define BBIO_2WIRE_CS_HIGH 0b00000101 +#define BBIO_2WIRE_READ_BYTE 0b00000110 +#define BBIO_2WIRE_READ_BIT 0b00000111 +#define BBIO_2WIRE_PEEK_INPUT 0b00001000 +#define BBIO_2WIRE_CLK_TICK 0b00001001 +#define BBIO_2WIRE_CLK_LOW 0b00001010 +#define BBIO_2WIRE_CLK_HIGH 0b00001011 +#define BBIO_2WIRE_DATA_LOW 0b00001100 +#define BBIO_2WIRE_DATA_HIGH 0b00001101 +#define BBIO_2WIRE_BULK_TRANSFER 0b00010000 +#define BBIO_2WIRE_BULK_CLK 0b00100000 +#define BBIO_2WIRE_BULK_BIT 0b00110000 +#define BBIO_2WIRE_CONFIG_PERIPH 0b01000000 +#define BBIO_2WIRE_SET_SPEED 0b01100000 +#define BBIO_2WIRE_CONFIG 0b10000000 + int cmd_bbio(t_hydra_console *con); diff --git a/hydrabus/hydrabus_bbio_twowire.c b/hydrabus/hydrabus_bbio_twowire.c new file mode 100644 index 00000000..f01d86d0 --- /dev/null +++ b/hydrabus/hydrabus_bbio_twowire.c @@ -0,0 +1,146 @@ +/* + * HydraBus/HydraNFC + * + * Copyright (C) 2014-2016 Benjamin VERNOUX + * Copyright (C) 2016 Nicolas OBERLI + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" +#include "tokenline.h" +#include +#include +#include + +#include "hydrabus_bbio.h" +#include "hydrabus_mode_twowire.h" + +void bbio_mode_twowire(t_hydra_console *con) +{ + uint8_t bbio_subcommand, i; + uint8_t rx_data[16], tx_data[16]; + uint8_t data; + mode_config_proto_t* proto = &con->mode->proto; + + init_proto_default(con); + twowire_pin_init(con); + tim_init(con); + twowire_clk_low(); + twowire_sda_low(); + + while (!USER_BUTTON) { + if(chSequentialStreamRead(con->sdu, &bbio_subcommand, 1) == 1) { + switch(bbio_subcommand) { + case BBIO_RESET: + return; + case BBIO_2WIRE_READ_BYTE: + rx_data[0] = twowire_read_u8(con); + cprint(con, (char *)&rx_data[0], 1); + break; + case BBIO_2WIRE_READ_BIT: + rx_data[0] = twowire_read_bit_clock(); + cprint(con, (char *)&rx_data[0], 1); + break; + case BBIO_2WIRE_PEEK_INPUT: + rx_data[0] = twowire_read_bit(); + cprint(con, (char *)&rx_data[0], 1); + break; + case BBIO_2WIRE_CLK_TICK: + twowire_clock(); + cprint(con, "\x01", 1); + break; + case BBIO_2WIRE_CLK_LOW: + twowire_clk_low(); + cprint(con, "\x01", 1); + break; + case BBIO_2WIRE_CLK_HIGH: + twowire_clk_high(); + cprint(con, "\x01", 1); + break; + case BBIO_2WIRE_DATA_LOW: + twowire_sda_low(); + cprint(con, "\x01", 1); + break; + case BBIO_2WIRE_DATA_HIGH: + twowire_sda_high(); + cprint(con, "\x01", 1); + break; + default: + if ((bbio_subcommand & BBIO_2WIRE_BULK_TRANSFER) == BBIO_2WIRE_BULK_TRANSFER) { + // data contains the number of bytes to + // write + data = (bbio_subcommand & 0b1111) + 1; + + chSequentialStreamRead(con->sdu, tx_data, data); + for(i=0; isdu, &tx_data[0], 1); + if(proto->dev_bit_lsb_msb == DEV_SPI_FIRSTBIT_LSB) { + for (i=0; i>i) & 1); + } + } else { + for (i=0; i>(7-i)) & 1); + } + } + cprint(con, "\x01", 1); + + } else if ((bbio_subcommand & BBIO_2WIRE_BULK_CLK) == BBIO_2WIRE_BULK_CLK) { + // data contains the number of bytes to + // write + data = (bbio_subcommand & 0b1111) + 1; + + for(i=0; idev_speed = 5000; + break; + case 1: + proto->dev_speed = 50000; + break; + case 2: + proto->dev_speed = 100000; + break; + case 3: + proto->dev_speed = 1000000; + break; + } + tim_set_prescaler(con); + } else if ((bbio_subcommand & BBIO_2WIRE_CONFIG) == BBIO_2WIRE_CONFIG) { + if(bbio_subcommand & 0b10){ + proto->dev_bit_lsb_msb = DEV_SPI_FIRSTBIT_MSB; + } else { + proto->dev_bit_lsb_msb = DEV_SPI_FIRSTBIT_LSB; + } + cprint(con, "\x01", 1); + } else if ((bbio_subcommand & BBIO_2WIRE_CONFIG_PERIPH) == BBIO_2WIRE_CONFIG_PERIPH) { + cprint(con, "\x01", 1); + } + + } + } + } +} diff --git a/hydrabus/hydrabus_bbio_twowire.h b/hydrabus/hydrabus_bbio_twowire.h new file mode 100644 index 00000000..7c8ae2d9 --- /dev/null +++ b/hydrabus/hydrabus_bbio_twowire.h @@ -0,0 +1,20 @@ +/* + * HydraBus/HydraNFC + * + * Copyright (C) 2016 Nicolas OBERLI + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +void bbio_twowire_init_proto_default(t_hydra_console *con); +void bbio_mode_twowire(t_hydra_console *con); diff --git a/hydrabus/hydrabus_mode_twowire.c b/hydrabus/hydrabus_mode_twowire.c index 134a0223..cc8989da 100644 --- a/hydrabus/hydrabus_mode_twowire.c +++ b/hydrabus/hydrabus_mode_twowire.c @@ -35,7 +35,7 @@ static const char* str_prompt_twowire[] = { "twowire1" PROMPT, }; -static void init_proto_default(t_hydra_console *con) +void init_proto_default(t_hydra_console *con) { mode_config_proto_t* proto = &con->mode->proto; @@ -44,8 +44,8 @@ static void init_proto_default(t_hydra_console *con) proto->dev_gpio_mode = MODE_CONFIG_DEV_GPIO_OUT_PUSHPULL; proto->dev_gpio_pull = MODE_CONFIG_DEV_GPIO_NOPULL; proto->dev_bit_lsb_msb = DEV_SPI_FIRSTBIT_MSB; + proto->dev_speed = TWOWIRE_MAX_FREQ; - config.divider = 1; config.clk_pin = 3; config.sda_pin = 4; } @@ -61,10 +61,10 @@ static void show_params(t_hydra_console *con) "floating"); cprintf(con, "Frequency: %dHz\r\nBit order: %s first\r\n", - (TWOWIRE_MAX_FREQ/(int)config.divider), proto->dev_bit_lsb_msb == DEV_SPI_FIRSTBIT_MSB ? "MSB" : "LSB"); + (proto->dev_speed), proto->dev_bit_lsb_msb == DEV_SPI_FIRSTBIT_MSB ? "MSB" : "LSB"); } -static bool twowire_pin_init(t_hydra_console *con) +bool twowire_pin_init(t_hydra_console *con) { mode_config_proto_t* proto = &con->mode->proto; @@ -75,12 +75,13 @@ static bool twowire_pin_init(t_hydra_console *con) return true; } -static void tim_init(void) +void tim_init(t_hydra_console *con) { + mode_config_proto_t* proto = &con->mode->proto; htim.Instance = TIM4; htim.Init.Period = 42 - 1; - htim.Init.Prescaler = (config.divider) - 1; + htim.Init.Prescaler = (TWOWIRE_MAX_FREQ/proto->dev_speed) - 1; htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim.Init.CounterMode = TIM_COUNTERMODE_UP; @@ -91,11 +92,13 @@ static void tim_init(void) HAL_TIM_Base_Start(&htim); } -static void tim_set_prescaler(void) +void tim_set_prescaler(t_hydra_console *con) { + mode_config_proto_t* proto = &con->mode->proto; + HAL_TIM_Base_Stop(&htim); HAL_TIM_Base_DeInit(&htim); - htim.Init.Prescaler = (config.divider) - 1; + htim.Init.Prescaler = (TWOWIRE_MAX_FREQ/proto->dev_speed) - 1; HAL_TIM_Base_Init(&htim); TIM4->SR &= ~TIM_SR_UIF; //clear overflow flag HAL_TIM_Base_Start(&htim); @@ -115,17 +118,17 @@ static void twowire_sda_mode_output(t_hydra_console *con) proto->dev_gpio_mode, proto->dev_gpio_pull); } -static inline void twowire_sda_high(void) +inline void twowire_sda_high(void) { bsp_gpio_set(BSP_GPIO_PORTB, config.sda_pin); } -static inline void twowire_sda_low(void) +inline void twowire_sda_low(void) { bsp_gpio_clr(BSP_GPIO_PORTB, config.sda_pin); } -static inline void twowire_clk_high(void) +inline void twowire_clk_high(void) { while (!(TIM4->SR & TIM_SR_UIF)) { } @@ -133,7 +136,7 @@ static inline void twowire_clk_high(void) TIM4->SR &= ~TIM_SR_UIF; //clear overflow flag } -static inline void twowire_clk_low(void) +inline void twowire_clk_low(void) { while (!(TIM4->SR & TIM_SR_UIF)) { } @@ -141,13 +144,13 @@ static inline void twowire_clk_low(void) TIM4->SR &= ~TIM_SR_UIF; //clear overflow flag } -static inline void twowire_clock(void) +inline void twowire_clock(void) { twowire_clk_high(); twowire_clk_low(); } -static void twowire_send_bit(uint8_t bit) +void twowire_send_bit(uint8_t bit) { if (bit) { twowire_sda_high(); @@ -157,12 +160,12 @@ static void twowire_send_bit(uint8_t bit) twowire_clock(); } -static uint8_t twowire_read_bit(void) +uint8_t twowire_read_bit(void) { return bsp_gpio_pin_read(BSP_GPIO_PORTB, config.sda_pin); } -static uint8_t twowire_read_bit_clock(void) +uint8_t twowire_read_bit_clock(void) { uint8_t bit; twowire_clock(); @@ -212,7 +215,7 @@ static void bitr(t_hydra_console *con) cprintf(con, hydrabus_mode_str_read_one_u8, rx_data); } -static void twowire_write_u8(t_hydra_console *con, uint8_t tx_data) +void twowire_write_u8(t_hydra_console *con, uint8_t tx_data) { mode_config_proto_t* proto = &con->mode->proto; uint8_t i; @@ -230,7 +233,7 @@ static void twowire_write_u8(t_hydra_console *con, uint8_t tx_data) } } -static uint8_t twowire_read_u8(t_hydra_console *con) +uint8_t twowire_read_u8(t_hydra_console *con) { mode_config_proto_t* proto = &con->mode->proto; uint8_t value; @@ -262,7 +265,7 @@ static int init(t_hydra_console *con, t_tokenline_parsed *p) tokens_used = 1 + exec(con, p, 1); twowire_pin_init(con); - tim_init(); + tim_init(con); twowire_clk_low(); twowire_sda_low(); @@ -309,8 +312,8 @@ static int exec(t_hydra_console *con, t_tokenline_parsed *p, int token_pos) if(arg_float > TWOWIRE_MAX_FREQ) { cprintf(con, "Frequency too high\r\n"); } else { - config.divider = TWOWIRE_MAX_FREQ/(int)arg_float; - tim_set_prescaler(); + proto->dev_speed = (int)arg_float; + tim_set_prescaler(con); } break; default: diff --git a/hydrabus/hydrabus_mode_twowire.h b/hydrabus/hydrabus_mode_twowire.h index 4483f01e..52eb4394 100644 --- a/hydrabus/hydrabus_mode_twowire.h +++ b/hydrabus/hydrabus_mode_twowire.h @@ -22,7 +22,21 @@ #define TWOWIRE_MAX_FREQ 1000000 typedef struct { - uint32_t divider; uint8_t clk_pin; uint8_t sda_pin; } twowire_config; + +void init_proto_default(t_hydra_console *con); +bool twowire_pin_init(t_hydra_console *con); +void tim_init(t_hydra_console *con); +void tim_set_prescaler(t_hydra_console *con); +uint8_t twowire_read_u8(t_hydra_console *con); +void twowire_write_u8(t_hydra_console *con, uint8_t tx_data); +inline void twowire_clock(void); +inline void twowire_clk_low(void); +inline void twowire_clk_high(void); +inline void twowire_sda_low(void); +inline void twowire_sda_high(void); +void twowire_send_bit(uint8_t bit); +uint8_t twowire_read_bit(void); +uint8_t twowire_read_bit_clock(void);