diff --git a/embed/firmware/main.c b/embed/firmware/main.c index e2fd288a38..bee97894a6 100644 --- a/embed/firmware/main.c +++ b/embed/firmware/main.c @@ -58,6 +58,7 @@ int main(void) #if TREZOR_MODEL == 1 display_init(); + touch_init(); #endif #if TREZOR_MODEL == T diff --git a/embed/trezorhal/touch.c b/embed/trezorhal/touch.c index 3fbbb5a312..7b5bd1b597 100644 --- a/embed/trezorhal/touch.c +++ b/embed/trezorhal/touch.c @@ -18,165 +18,13 @@ */ #include STM32_HAL_H - -#include - -#include "common.h" -#include "secbool.h" #include "touch.h" -#define TOUCH_ADDRESS (0x38U << 1) // the HAL requires the 7-bit address to be shifted by one bit -#define TOUCH_PACKET_SIZE 7U -#define EVENT_PRESS_DOWN 0x00U -#define EVENT_CONTACT 0x80U -#define EVENT_LIFT_UP 0x40U -#define EVENT_NO_EVENT 0xC0U -#define GESTURE_NO_GESTURE 0x00U -#define X_POS_MSB (touch_data[3] & 0x0FU) -#define X_POS_LSB (touch_data[4]) -#define Y_POS_MSB (touch_data[5] & 0x0FU) -#define Y_POS_LSB (touch_data[6]) - -static I2C_HandleTypeDef i2c_handle; - -static void touch_default_pin_state(void) { - // set power off and other pins as per section 3.5 of FT6236 datasheet - HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET); // CTP_ON/PB10 (active low) i.e.- CTPM power off when set/high/log 1 - HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET); // CTP_I2C_SCL/PB6 - HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET); // CTP_I2C_SDA/PB7 - HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_RESET); // CTP_INT/PC4 normally an input, but drive low as an output while powered off - HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_RESET); // CTP_REST/PC5 (active low) i.e.- CTPM held in reset until released - - // set above pins to OUTPUT / NOPULL - GPIO_InitTypeDef GPIO_InitStructure; - - GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStructure.Pin = GPIO_PIN_10 | GPIO_PIN_6 | GPIO_PIN_7; - HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); - GPIO_InitStructure.Pin = GPIO_PIN_4 | GPIO_PIN_5; - HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); - - // in-case power was on, or CTPM was active make sure to wait long enough - // for these changes to take effect. a reset needs to be low for - // a minimum of 5ms. also wait for power circuitry to stabilize (if it changed). - HAL_Delay(100); // 100ms (being conservative) -} - -static void touch_active_pin_state(void) { - HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET); // CTP_ON/PB10 - HAL_Delay(10); // we need to wait until the circuit fully kicks-in - - GPIO_InitTypeDef GPIO_InitStructure; - - // configure CTP I2C SCL and SDA GPIO lines (PB6 & PB7) - GPIO_InitStructure.Mode = GPIO_MODE_AF_OD; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; // I2C is a KHz bus and low speed is still good into the low MHz - GPIO_InitStructure.Alternate = GPIO_AF4_I2C1; - GPIO_InitStructure.Pin = GPIO_PIN_6 | GPIO_PIN_7; - HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); - - // PC4 capacitive touch panel module (CTPM) interrupt (INT) input - GPIO_InitStructure.Mode = GPIO_MODE_INPUT; - GPIO_InitStructure.Pull = GPIO_PULLUP; - GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; - GPIO_InitStructure.Pin = GPIO_PIN_4; - HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); - - HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_SET); // release CTPM reset - HAL_Delay(310); // "Time of starting to report point after resetting" min is 300ms, giving an extra 10ms -} - -void touch_init(void) { - touch_default_pin_state(); -} - -void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c) { - // enable I2C clock - __HAL_RCC_I2C1_CLK_ENABLE(); - // GPIO have already been initialised by touch_init -} - -void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c) { - __HAL_RCC_I2C1_CLK_DISABLE(); -} - -void touch_power_on(void) { - if (i2c_handle.Instance) { - return; - } - - // turn on CTP circuitry - touch_active_pin_state(); - HAL_Delay(50); - - // I2C device interface configuration - i2c_handle.Instance = I2C1; - i2c_handle.Init.ClockSpeed = 400000; - i2c_handle.Init.DutyCycle = I2C_DUTYCYCLE_16_9; - i2c_handle.Init.OwnAddress1 = 0xFE; // master - i2c_handle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; - i2c_handle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; - i2c_handle.Init.OwnAddress2 = 0; - i2c_handle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; - i2c_handle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; - - if (HAL_OK != HAL_I2C_Init(&i2c_handle)) { - ensure(secfalse, NULL); - return; - } - - // set register 0xA4 G_MODE to interrupt polling mode (0x00). basically, CTPM keeps this input line (to PC4) low while a finger is on the screen. - uint8_t touch_panel_config[] = {0xA4, 0x00}; - ensure(sectrue * (HAL_OK == HAL_I2C_Master_Transmit(&i2c_handle, TOUCH_ADDRESS, touch_panel_config, sizeof(touch_panel_config), 10)), NULL); -} - -void touch_power_off(void) { - if (i2c_handle.Instance) { - HAL_I2C_DeInit(&i2c_handle); - i2c_handle.Instance = NULL; - } - // turn off CTP circuitry - HAL_Delay(50); - touch_default_pin_state(); -} - -uint32_t touch_read(void) -{ - static uint8_t touch_data[TOUCH_PACKET_SIZE], previous_touch_data[TOUCH_PACKET_SIZE]; - - uint8_t outgoing[] = {0x00}; // start reading from address 0x00 - if (HAL_OK != HAL_I2C_Master_Transmit(&i2c_handle, TOUCH_ADDRESS, outgoing, sizeof(outgoing), 1)) { - return 0; - } - - if (HAL_OK != HAL_I2C_Master_Receive(&i2c_handle, TOUCH_ADDRESS, touch_data, TOUCH_PACKET_SIZE, 1)) { - return 0; // read failure - } - - if (0 == memcmp(previous_touch_data, touch_data, TOUCH_PACKET_SIZE)) { - return 0; // polled and got the same event again - } else { - memcpy(previous_touch_data, touch_data, TOUCH_PACKET_SIZE); - } - - const uint32_t number_of_touch_points = touch_data[2] & 0x0F; // valid values are 0, 1, 2 (invalid 0xF before first touch) (tested with FT6206) - const uint32_t event_flag = touch_data[3] & 0xC0; - if (touch_data[1] == GESTURE_NO_GESTURE) { - uint32_t xy = touch_pack_xy((X_POS_MSB << 8) | X_POS_LSB, (Y_POS_MSB << 8) | Y_POS_LSB); - if ((number_of_touch_points == 1) && (event_flag == EVENT_PRESS_DOWN)) { - return TOUCH_START | xy; - } else if ((number_of_touch_points == 1) && (event_flag == EVENT_CONTACT)) { - return TOUCH_MOVE | xy; - } else if ((number_of_touch_points == 0) && (event_flag == EVENT_LIFT_UP)) { - return TOUCH_END | xy; - } - } - - return 0; -} +#if TREZOR_MODEL == T +#include "touch_t.h" +#elif TREZOR_MODEL == 1 +#include "touch_1.h" +#endif uint32_t touch_click(void) { @@ -192,12 +40,3 @@ uint32_t touch_click(void) // return last touch coordinate return r; } - -uint32_t touch_is_detected(void) -{ - // check the interrupt line coming in from the CTPM. - // the line goes low when a touch event is actively detected. - // reference section 1.2 of "Application Note for FT6x06 CTPM". - // we configure the touch controller to use "interrupt polling mode". - return GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_4); -} diff --git a/embed/trezorhal/touch_1.h b/embed/trezorhal/touch_1.h new file mode 100644 index 0000000000..ce111ab3ba --- /dev/null +++ b/embed/trezorhal/touch_1.h @@ -0,0 +1,48 @@ +#define BTN_PIN_LEFT GPIO_PIN_5 +#define BTN_PIN_RIGHT GPIO_PIN_2 + +void touch_init(void) { + __HAL_RCC_GPIOC_CLK_ENABLE(); + + GPIO_InitTypeDef GPIO_InitStructure; + + // PC4 capacitive touch panel module (CTPM) interrupt (INT) input + GPIO_InitStructure.Mode = GPIO_MODE_INPUT; + GPIO_InitStructure.Pull = GPIO_PULLUP; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStructure.Pin = BTN_PIN_LEFT | BTN_PIN_RIGHT; + HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); +} + +void touch_power_on(void) { } + +void touch_power_off(void) { } + +uint32_t touch_read(void) +{ + static char last_left = 0, last_right = 0; + char left = (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, BTN_PIN_LEFT)); + char right = (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, BTN_PIN_RIGHT)); + if (last_left != left) { + last_left = left; + if (left) { + return TOUCH_START | touch_pack_xy(0, 63); + } else { + return TOUCH_END | touch_pack_xy(0, 63); + } + } + if (last_right != right) { + last_right = right; + if (right) { + return TOUCH_START | touch_pack_xy(127, 63); + } else { + return TOUCH_END | touch_pack_xy(127, 63); + } + } + return 0; +} + +uint32_t touch_is_detected(void) +{ + return (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, BTN_PIN_LEFT)) || (GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, BTN_PIN_RIGHT)); +} diff --git a/embed/trezorhal/touch_t.h b/embed/trezorhal/touch_t.h new file mode 100644 index 0000000000..b2d602af53 --- /dev/null +++ b/embed/trezorhal/touch_t.h @@ -0,0 +1,166 @@ +#include + +#include "common.h" +#include "secbool.h" + +#define TOUCH_ADDRESS (0x38U << 1) // the HAL requires the 7-bit address to be shifted by one bit +#define TOUCH_PACKET_SIZE 7U +#define EVENT_PRESS_DOWN 0x00U +#define EVENT_CONTACT 0x80U +#define EVENT_LIFT_UP 0x40U +#define EVENT_NO_EVENT 0xC0U +#define GESTURE_NO_GESTURE 0x00U +#define X_POS_MSB (touch_data[3] & 0x0FU) +#define X_POS_LSB (touch_data[4]) +#define Y_POS_MSB (touch_data[5] & 0x0FU) +#define Y_POS_LSB (touch_data[6]) + +static I2C_HandleTypeDef i2c_handle; + +static void touch_default_pin_state(void) { + // set power off and other pins as per section 3.5 of FT6236 datasheet + HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET); // CTP_ON/PB10 (active low) i.e.- CTPM power off when set/high/log 1 + HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET); // CTP_I2C_SCL/PB6 + HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET); // CTP_I2C_SDA/PB7 + HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_RESET); // CTP_INT/PC4 normally an input, but drive low as an output while powered off + HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_RESET); // CTP_REST/PC5 (active low) i.e.- CTPM held in reset until released + + // set above pins to OUTPUT / NOPULL + GPIO_InitTypeDef GPIO_InitStructure; + + GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStructure.Pin = GPIO_PIN_10 | GPIO_PIN_6 | GPIO_PIN_7; + HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); + GPIO_InitStructure.Pin = GPIO_PIN_4 | GPIO_PIN_5; + HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); + + // in-case power was on, or CTPM was active make sure to wait long enough + // for these changes to take effect. a reset needs to be low for + // a minimum of 5ms. also wait for power circuitry to stabilize (if it changed). + HAL_Delay(100); // 100ms (being conservative) +} + +static void touch_active_pin_state(void) { + HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET); // CTP_ON/PB10 + HAL_Delay(10); // we need to wait until the circuit fully kicks-in + + GPIO_InitTypeDef GPIO_InitStructure; + + // configure CTP I2C SCL and SDA GPIO lines (PB6 & PB7) + GPIO_InitStructure.Mode = GPIO_MODE_AF_OD; + GPIO_InitStructure.Pull = GPIO_NOPULL; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; // I2C is a KHz bus and low speed is still good into the low MHz + GPIO_InitStructure.Alternate = GPIO_AF4_I2C1; + GPIO_InitStructure.Pin = GPIO_PIN_6 | GPIO_PIN_7; + HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); + + // PC4 capacitive touch panel module (CTPM) interrupt (INT) input + GPIO_InitStructure.Mode = GPIO_MODE_INPUT; + GPIO_InitStructure.Pull = GPIO_PULLUP; + GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW; + GPIO_InitStructure.Pin = GPIO_PIN_4; + HAL_GPIO_Init(GPIOC, &GPIO_InitStructure); + + HAL_GPIO_WritePin(GPIOC, GPIO_PIN_5, GPIO_PIN_SET); // release CTPM reset + HAL_Delay(310); // "Time of starting to report point after resetting" min is 300ms, giving an extra 10ms +} + +void touch_init(void) { + touch_default_pin_state(); +} + +void HAL_I2C_MspInit(I2C_HandleTypeDef *hi2c) { + // enable I2C clock + __HAL_RCC_I2C1_CLK_ENABLE(); + // GPIO have already been initialised by touch_init +} + +void HAL_I2C_MspDeInit(I2C_HandleTypeDef *hi2c) { + __HAL_RCC_I2C1_CLK_DISABLE(); +} + +void touch_power_on(void) { + if (i2c_handle.Instance) { + return; + } + + // turn on CTP circuitry + touch_active_pin_state(); + HAL_Delay(50); + + // I2C device interface configuration + i2c_handle.Instance = I2C1; + i2c_handle.Init.ClockSpeed = 400000; + i2c_handle.Init.DutyCycle = I2C_DUTYCYCLE_16_9; + i2c_handle.Init.OwnAddress1 = 0xFE; // master + i2c_handle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + i2c_handle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; + i2c_handle.Init.OwnAddress2 = 0; + i2c_handle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; + i2c_handle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; + + if (HAL_OK != HAL_I2C_Init(&i2c_handle)) { + ensure(secfalse, NULL); + return; + } + + // set register 0xA4 G_MODE to interrupt polling mode (0x00). basically, CTPM keeps this input line (to PC4) low while a finger is on the screen. + uint8_t touch_panel_config[] = {0xA4, 0x00}; + ensure(sectrue * (HAL_OK == HAL_I2C_Master_Transmit(&i2c_handle, TOUCH_ADDRESS, touch_panel_config, sizeof(touch_panel_config), 10)), NULL); +} + +void touch_power_off(void) { + if (i2c_handle.Instance) { + HAL_I2C_DeInit(&i2c_handle); + i2c_handle.Instance = NULL; + } + // turn off CTP circuitry + HAL_Delay(50); + touch_default_pin_state(); +} + +uint32_t touch_read(void) +{ + static uint8_t touch_data[TOUCH_PACKET_SIZE], previous_touch_data[TOUCH_PACKET_SIZE]; + + uint8_t outgoing[] = {0x00}; // start reading from address 0x00 + if (HAL_OK != HAL_I2C_Master_Transmit(&i2c_handle, TOUCH_ADDRESS, outgoing, sizeof(outgoing), 1)) { + return 0; + } + + if (HAL_OK != HAL_I2C_Master_Receive(&i2c_handle, TOUCH_ADDRESS, touch_data, TOUCH_PACKET_SIZE, 1)) { + return 0; // read failure + } + + if (0 == memcmp(previous_touch_data, touch_data, TOUCH_PACKET_SIZE)) { + return 0; // polled and got the same event again + } else { + memcpy(previous_touch_data, touch_data, TOUCH_PACKET_SIZE); + } + + const uint32_t number_of_touch_points = touch_data[2] & 0x0F; // valid values are 0, 1, 2 (invalid 0xF before first touch) (tested with FT6206) + const uint32_t event_flag = touch_data[3] & 0xC0; + if (touch_data[1] == GESTURE_NO_GESTURE) { + uint32_t xy = touch_pack_xy((X_POS_MSB << 8) | X_POS_LSB, (Y_POS_MSB << 8) | Y_POS_LSB); + if ((number_of_touch_points == 1) && (event_flag == EVENT_PRESS_DOWN)) { + return TOUCH_START | xy; + } else if ((number_of_touch_points == 1) && (event_flag == EVENT_CONTACT)) { + return TOUCH_MOVE | xy; + } else if ((number_of_touch_points == 0) && (event_flag == EVENT_LIFT_UP)) { + return TOUCH_END | xy; + } + } + + return 0; +} + +uint32_t touch_is_detected(void) +{ + // check the interrupt line coming in from the CTPM. + // the line goes low when a touch event is actively detected. + // reference section 1.2 of "Application Note for FT6x06 CTPM". + // we configure the touch controller to use "interrupt polling mode". + return GPIO_PIN_RESET == HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_4); +} diff --git a/src1/main.py b/src1/main.py index 059565a479..f3dc2dda88 100644 --- a/src1/main.py +++ b/src1/main.py @@ -1,3 +1,7 @@ +import usb + +usb.bus.open() + import trezorio as io from trezorui import Display diff --git a/src1/usb.py b/src1/usb.py new file mode 100644 index 0000000000..2582c9b078 --- /dev/null +++ b/src1/usb.py @@ -0,0 +1,29 @@ +import trezorio as io + +iface_wire = io.WebUSB( + iface_num=0, + ep_in=0x81, + ep_out=0x01, +) + +iface_vcp = io.VCP( + iface_num=2, + data_iface_num=3, + ep_in=0x83, + ep_out=0x03, + ep_cmd=0x84, +) + +bus = io.USB( + vendor_id=0x1209, + product_id=0x53C1, + release_num=0x0100, + manufacturer="SatoshiLabs", + product="TREZOR", + interface="TREZOR Interface", + serial_number="1234", + usb21_landing=False, +) + +bus.add(iface_wire) +bus.add(iface_vcp)