diff --git a/board/board.h b/board/board.h index f89c601..9e250d8 100644 --- a/board/board.h +++ b/board/board.h @@ -9,6 +9,7 @@ #ifdef PANDA #include "drivers/fan.h" #include "drivers/rtc.h" + #include "drivers/clock_source.h" #include "boards/white.h" #include "boards/grey.h" #include "boards/black.h" diff --git a/board/board_declarations.h b/board/board_declarations.h index d5e9e06..b6f7772 100644 --- a/board/board_declarations.h +++ b/board/board_declarations.h @@ -12,6 +12,7 @@ typedef uint32_t (*board_read_current)(void); typedef void (*board_set_ir_power)(uint8_t percentage); typedef void (*board_set_fan_power)(uint8_t percentage); typedef void (*board_set_phone_power)(bool enabled); +typedef void (*board_set_clock_source_mode)(uint8_t mode); struct board { const char *board_type; @@ -29,6 +30,7 @@ struct board { board_set_ir_power set_ir_power; board_set_fan_power set_fan_power; board_set_phone_power set_phone_power; + board_set_clock_source_mode set_clock_source_mode; }; // ******************* Definitions ******************** diff --git a/board/boards/black.h b/board/boards/black.h index 5730598..70248c7 100644 --- a/board/boards/black.h +++ b/board/boards/black.h @@ -154,6 +154,10 @@ void black_set_phone_power(bool enabled){ UNUSED(enabled); } +void black_set_clock_source_mode(uint8_t mode){ + UNUSED(mode); +} + void black_init(void) { common_init_gpio(); @@ -239,5 +243,6 @@ const board board_black = { .read_current = black_read_current, .set_fan_power = black_set_fan_power, .set_ir_power = black_set_ir_power, - .set_phone_power = black_set_phone_power + .set_phone_power = black_set_phone_power, + .set_clock_source_mode = black_set_clock_source_mode }; diff --git a/board/boards/common.h b/board/boards/common.h index 7343809..040ae39 100644 --- a/board/boards/common.h +++ b/board/boards/common.h @@ -65,7 +65,7 @@ void peripherals_init(void){ RCC->APB1ENR |= RCC_APB1ENR_PWREN; // for RTC config RCC->APB2ENR |= RCC_APB2ENR_USART1EN; RCC->AHB2ENR |= RCC_AHB2ENR_OTGFSEN; - //RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; + RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; // clock source timer RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; diff --git a/board/boards/dos.h b/board/boards/dos.h index afccd37..91bb313 100644 --- a/board/boards/dos.h +++ b/board/boards/dos.h @@ -132,6 +132,10 @@ uint32_t dos_read_current(void){ return 0U; } +void dos_set_clock_source_mode(uint8_t mode){ + clock_source_init(mode); +} + void dos_init(void) { common_init_gpio(); @@ -189,6 +193,9 @@ void dos_init(void) { // init multiplexer can_set_obd(car_harness_status, false); + + // Init clock source as internal free running + dos_set_clock_source_mode(CLOCK_SOURCE_MODE_FREE_RUNNING); } const harness_configuration dos_harness_config = { @@ -220,5 +227,6 @@ const board board_dos = { .read_current = dos_read_current, .set_fan_power = dos_set_fan_power, .set_ir_power = dos_set_ir_power, - .set_phone_power = dos_set_phone_power + .set_phone_power = dos_set_phone_power, + .set_clock_source_mode = dos_set_clock_source_mode }; diff --git a/board/boards/grey.h b/board/boards/grey.h index 1c7278d..1a7668d 100644 --- a/board/boards/grey.h +++ b/board/boards/grey.h @@ -48,5 +48,6 @@ const board board_grey = { .read_current = white_read_current, .set_fan_power = white_set_fan_power, .set_ir_power = white_set_ir_power, - .set_phone_power = white_set_phone_power + .set_phone_power = white_set_phone_power, + .set_clock_source_mode = white_set_clock_source_mode }; \ No newline at end of file diff --git a/board/boards/pedal.h b/board/boards/pedal.h index c67d391..b3d00f5 100644 --- a/board/boards/pedal.h +++ b/board/boards/pedal.h @@ -77,6 +77,10 @@ void pedal_set_phone_power(bool enabled){ UNUSED(enabled); } +void pedal_set_clock_source_mode(uint8_t mode){ + UNUSED(mode); +} + void pedal_init(void) { common_init_gpio(); @@ -113,5 +117,6 @@ const board board_pedal = { .read_current = pedal_read_current, .set_fan_power = pedal_set_fan_power, .set_ir_power = pedal_set_ir_power, - .set_phone_power = pedal_set_phone_power + .set_phone_power = pedal_set_phone_power, + .set_clock_source_mode = pedal_set_clock_source_mode }; \ No newline at end of file diff --git a/board/boards/uno.h b/board/boards/uno.h index de430cb..aa5b06f 100644 --- a/board/boards/uno.h +++ b/board/boards/uno.h @@ -175,6 +175,10 @@ uint32_t uno_read_current(void){ return 0U; } +void uno_set_clock_source_mode(uint8_t mode){ + UNUSED(mode); +} + void uno_init(void) { common_init_gpio(); @@ -282,5 +286,6 @@ const board board_uno = { .read_current = uno_read_current, .set_fan_power = uno_set_fan_power, .set_ir_power = uno_set_ir_power, - .set_phone_power = uno_set_phone_power + .set_phone_power = uno_set_phone_power, + .set_clock_source_mode = uno_set_clock_source_mode }; diff --git a/board/boards/white.h b/board/boards/white.h index 1be0702..b6e639f 100644 --- a/board/boards/white.h +++ b/board/boards/white.h @@ -242,6 +242,10 @@ void white_set_phone_power(bool enabled){ UNUSED(enabled); } +void white_set_clock_source_mode(uint8_t mode){ + UNUSED(mode); +} + void white_grey_common_init(void) { common_init_gpio(); @@ -343,5 +347,6 @@ const board board_white = { .read_current = white_read_current, .set_fan_power = white_set_fan_power, .set_ir_power = white_set_ir_power, - .set_phone_power = white_set_phone_power + .set_phone_power = white_set_phone_power, + .set_clock_source_mode = white_set_clock_source_mode }; diff --git a/board/drivers/clock_source.h b/board/drivers/clock_source.h new file mode 100644 index 0000000..966dee4 --- /dev/null +++ b/board/drivers/clock_source.h @@ -0,0 +1,100 @@ + +#define CLOCK_SOURCE_MODE_DISABLED 0U +#define CLOCK_SOURCE_MODE_FREE_RUNNING 1U +#define CLOCK_SOURCE_MODE_EXTERNAL_SYNC 2U + +#define CLOCK_SOURCE_PERIOD_MS 50U +#define CLOCK_SOURCE_PULSE_LEN_MS 2U + +uint8_t clock_source_mode = CLOCK_SOURCE_MODE_DISABLED; + +void EXTI0_IRQ_Handler(void) { + volatile unsigned int pr = EXTI->PR & (1U << 0); + if (pr != 0U) { + if(clock_source_mode == CLOCK_SOURCE_MODE_EXTERNAL_SYNC){ + // TODO: Implement! + } + } + EXTI->PR = (1U << 0); +} + +void TIM1_UP_TIM10_IRQ_Handler(void) { + if((TIM1->SR & TIM_SR_UIF) != 0) { + if(clock_source_mode != CLOCK_SOURCE_MODE_DISABLED) { + // Start clock pulse + set_gpio_output(GPIOB, 14, true); + set_gpio_output(GPIOB, 15, true); + } + + // Reset interrupt + TIM1->SR &= ~(TIM_SR_UIF); + } +} + +void TIM1_CC_IRQ_Handler(void) { + if((TIM1->SR & TIM_SR_CC1IF) != 0) { + if(clock_source_mode != CLOCK_SOURCE_MODE_DISABLED) { + // End clock pulse + set_gpio_output(GPIOB, 14, false); + set_gpio_output(GPIOB, 15, false); + } + + // Reset interrupt + TIM1->SR &= ~(TIM_SR_CC1IF); + } +} + +void clock_source_init(uint8_t mode){ + // Setup external clock signal interrupt + REGISTER_INTERRUPT(EXTI0_IRQn, EXTI0_IRQ_Handler, 110U, FAULT_INTERRUPT_RATE_CLOCK_SOURCE) + register_set(&(SYSCFG->EXTICR[0]), SYSCFG_EXTICR1_EXTI0_PB, 0xFU); + register_set_bits(&(EXTI->IMR), (1U << 0)); + register_set_bits(&(EXTI->RTSR), (1U << 0)); + register_clear_bits(&(EXTI->FTSR), (1U << 0)); + + // Setup timer + REGISTER_INTERRUPT(TIM1_UP_TIM10_IRQn, TIM1_UP_TIM10_IRQ_Handler, (1200U / CLOCK_SOURCE_PERIOD_MS) , FAULT_INTERRUPT_RATE_TIM1) + REGISTER_INTERRUPT(TIM1_CC_IRQn, TIM1_CC_IRQ_Handler, (1200U / CLOCK_SOURCE_PERIOD_MS) , FAULT_INTERRUPT_RATE_TIM1) + register_set(&(TIM1->PSC), (9600-1), 0xFFFFU); // Tick on 0.1 ms + register_set(&(TIM1->ARR), ((CLOCK_SOURCE_PERIOD_MS*10U) - 1U), 0xFFFFU); // Period + register_set(&(TIM1->CCMR1), 0U, 0xFFFFU); // No output on compare + register_set_bits(&(TIM1->CCER), TIM_CCER_CC1E); // Enable compare 1 + register_set(&(TIM1->CCR1), (CLOCK_SOURCE_PULSE_LEN_MS*10U), 0xFFFFU); // Compare 1 value + register_set_bits(&(TIM1->DIER), TIM_DIER_UIE | TIM_DIER_CC1IE); // Enable interrupts + register_set(&(TIM1->CR1), TIM_CR1_CEN, 0x3FU); // Enable timer + + // Set mode + switch(mode) { + case CLOCK_SOURCE_MODE_DISABLED: + // No clock signal + NVIC_DisableIRQ(EXTI0_IRQn); + NVIC_DisableIRQ(TIM1_UP_TIM10_IRQn); + NVIC_DisableIRQ(TIM1_CC_IRQn); + + // Disable pulse if we were in the middle of it + set_gpio_output(GPIOB, 14, false); + set_gpio_output(GPIOB, 15, false); + + clock_source_mode = CLOCK_SOURCE_MODE_DISABLED; + break; + case CLOCK_SOURCE_MODE_FREE_RUNNING: + // Clock signal is based on internal timer + NVIC_DisableIRQ(EXTI0_IRQn); + NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn); + NVIC_EnableIRQ(TIM1_CC_IRQn); + + clock_source_mode = CLOCK_SOURCE_MODE_FREE_RUNNING; + break; + case CLOCK_SOURCE_MODE_EXTERNAL_SYNC: + // Clock signal is based on external timer + NVIC_EnableIRQ(EXTI0_IRQn); + NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn); + NVIC_EnableIRQ(TIM1_CC_IRQn); + + clock_source_mode = CLOCK_SOURCE_MODE_EXTERNAL_SYNC; + break; + default: + puts("Unknown clock source mode: "); puth(mode); puts("\n"); + break; + } +} \ No newline at end of file diff --git a/board/faults.h b/board/faults.h index 2c031cf..0825586 100644 --- a/board/faults.h +++ b/board/faults.h @@ -3,26 +3,28 @@ #define FAULT_STATUS_PERMANENT 2U // Fault types -#define FAULT_RELAY_MALFUNCTION (1U << 0) -#define FAULT_UNUSED_INTERRUPT_HANDLED (1U << 1) -#define FAULT_INTERRUPT_RATE_CAN_1 (1U << 2) -#define FAULT_INTERRUPT_RATE_CAN_2 (1U << 3) -#define FAULT_INTERRUPT_RATE_CAN_3 (1U << 4) -#define FAULT_INTERRUPT_RATE_TACH (1U << 5) -#define FAULT_INTERRUPT_RATE_GMLAN (1U << 6) -#define FAULT_INTERRUPT_RATE_INTERRUPTS (1U << 7) -#define FAULT_INTERRUPT_RATE_SPI_DMA (1U << 8) -#define FAULT_INTERRUPT_RATE_SPI_CS (1U << 9) -#define FAULT_INTERRUPT_RATE_UART_1 (1U << 10) -#define FAULT_INTERRUPT_RATE_UART_2 (1U << 11) -#define FAULT_INTERRUPT_RATE_UART_3 (1U << 12) -#define FAULT_INTERRUPT_RATE_UART_5 (1U << 13) -#define FAULT_INTERRUPT_RATE_UART_DMA (1U << 14) -#define FAULT_INTERRUPT_RATE_USB (1U << 15) -#define FAULT_INTERRUPT_RATE_TIM1 (1U << 16) -#define FAULT_INTERRUPT_RATE_TIM3 (1U << 17) -#define FAULT_REGISTER_DIVERGENT (1U << 18) -#define FAULT_INTERRUPT_RATE_KLINE_INIT (1U << 19) +#define FAULT_RELAY_MALFUNCTION (1U << 0) +#define FAULT_UNUSED_INTERRUPT_HANDLED (1U << 1) +#define FAULT_INTERRUPT_RATE_CAN_1 (1U << 2) +#define FAULT_INTERRUPT_RATE_CAN_2 (1U << 3) +#define FAULT_INTERRUPT_RATE_CAN_3 (1U << 4) +#define FAULT_INTERRUPT_RATE_TACH (1U << 5) +#define FAULT_INTERRUPT_RATE_GMLAN (1U << 6) +#define FAULT_INTERRUPT_RATE_INTERRUPTS (1U << 7) +#define FAULT_INTERRUPT_RATE_SPI_DMA (1U << 8) +#define FAULT_INTERRUPT_RATE_SPI_CS (1U << 9) +#define FAULT_INTERRUPT_RATE_UART_1 (1U << 10) +#define FAULT_INTERRUPT_RATE_UART_2 (1U << 11) +#define FAULT_INTERRUPT_RATE_UART_3 (1U << 12) +#define FAULT_INTERRUPT_RATE_UART_5 (1U << 13) +#define FAULT_INTERRUPT_RATE_UART_DMA (1U << 14) +#define FAULT_INTERRUPT_RATE_USB (1U << 15) +#define FAULT_INTERRUPT_RATE_TIM1 (1U << 16) +#define FAULT_INTERRUPT_RATE_TIM3 (1U << 17) +#define FAULT_REGISTER_DIVERGENT (1U << 18) +#define FAULT_INTERRUPT_RATE_KLINE_INIT (1U << 19) +#define FAULT_INTERRUPT_RATE_CLOCK_SOURCE (1U << 20) +#define FAULT_INTERRUPT_RATE_TIM9 (1U << 21) // Permanent faults #define PERMANENT_FAULTS 0U diff --git a/board/main.c b/board/main.c index 497ea5d..207e5dc 100644 --- a/board/main.c +++ b/board/main.c @@ -606,6 +606,10 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired) } } break; + // **** 0xf5: set clock source mode + case 0xf5: + current_board->set_clock_source_mode(setup->b.wValue.w); + break; default: puts("NO HANDLER "); puth(setup->b.bRequest); @@ -754,7 +758,7 @@ int main(void) { init_interrupts(true); // 1s timer - REGISTER_INTERRUPT(TIM1_BRK_TIM9_IRQn, TIM1_BRK_TIM9_IRQ_Handler, 2U, FAULT_INTERRUPT_RATE_TIM1) + REGISTER_INTERRUPT(TIM1_BRK_TIM9_IRQn, TIM1_BRK_TIM9_IRQ_Handler, 2U, FAULT_INTERRUPT_RATE_TIM9) // shouldn't have interrupts here, but just in case disable_interrupts(); diff --git a/python/__init__.py b/python/__init__.py index 605977d..c602305 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -148,6 +148,10 @@ class Panda(object): HW_TYPE_PEDAL = b'\x04' HW_TYPE_UNO = b'\x05' + CLOCK_SOURCE_MODE_DISABLED = 0 + CLOCK_SOURCE_MODE_FREE_RUNNING = 1 + CLOCK_SOURCE_MODE_EXTERNAL_SYNC = 2 + def __init__(self, serial=None, claim=True): self._serial = serial self._handle = None @@ -665,3 +669,7 @@ class Panda(object): # ****************** Phone ***************** def set_phone_power(self, enabled): self._handle.controlWrite(Panda.REQUEST_OUT, 0xb3, int(enabled), 0, b'') + + # ************** Clock Source ************** + def set_clock_source_mode(self, mode): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xf5, int(mode), 0, b'')