diff --git a/firmware/common/clkin.c b/firmware/common/clkin.c new file mode 100644 index 00000000..bef8b8a9 --- /dev/null +++ b/firmware/common/clkin.c @@ -0,0 +1,114 @@ +/* + * Copyright 2022 Great Scott Gadgets + * + * This file is part of HackRF. + * + * 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, 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; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include "gpdma.h" +#include +#include +#include +#include + +#define CLOCK_CYCLES_1_MS (204000) +#define MEASUREMENT_WINDOW_MS (50) +#define MEASUREMENT_CYCLES (CLOCK_CYCLES_1_MS * MEASUREMENT_WINDOW_MS) + +/* DMA linked list item */ +typedef struct { + uint32_t src; + uint32_t dest; + uint32_t next_lli; + uint32_t control; +} dma_lli; + +/* timer control register configuration sequence */ +typedef struct { + uint32_t first_tcr; + uint32_t second_tcr; +} tcr_sequence; + +dma_lli timer_dma_lli; +tcr_sequence reset; + +void clkin_detect_init(void) +{ + /* Timer3 triggers periodic measurement */ + timer_set_prescaler(TIMER3, 0); + timer_set_mode(TIMER3, TIMER_CTCR_MODE_TIMER); + TIMER3_MCR = TIMER_MCR_MR0R; + TIMER3_EMR = TIMER_EMR_EM0 | TIMER_EMR_EM3 | + (TIMER_EMR_EMC_SET << TIMER_EMR_EMC0_SHIFT) | + (TIMER_EMR_EMC_TOGGLE << TIMER_EMR_EMC3_SHIFT); + TIMER3_MR3 = MEASUREMENT_CYCLES; + TIMER3_MR0 = MEASUREMENT_CYCLES; + + /* Timer0 counts CLKIN */ + timer_set_prescaler(TIMER0, 0); + TIMER0_CCR = TIMER_CCR_CAP3RE; + GIMA_CAP0_3_IN = 0x20; // T3_MAT3 + + /* measure CLKIN signal on P2_5, pin 91, CTIN_2 */ + TIMER0_CTCR = TIMER_CTCR_MODE_COUNTER_RISING | TIMER_CTCR_CINSEL_CAPN_2; + scu_pinmux(P2_5, SCU_GPIO_PDN | SCU_CONF_FUNCTION1); + GIMA_CAP0_2_IN = 0x00; // CTIN_2 + + // temporarily testing with T0_CAP1, P1_12, pin 56, P28 pin 4 + //TIMER0_CTCR = TIMER_CTCR_MODE_COUNTER_RISING | TIMER_CTCR_CINSEL_CAPN_1; + //scu_pinmux(P1_12, SCU_GPIO_PDN | SCU_CONF_FUNCTION4); + //GIMA_CAP0_1_IN = 0x20; // T0_CAP1 + + reset.first_tcr = TIMER_TCR_CEN | TIMER_TCR_CRST; + reset.second_tcr = TIMER_TCR_CEN; + timer_dma_lli.src = (uint32_t) & (reset); + timer_dma_lli.dest = (uint32_t) & (TIMER0_TCR); + timer_dma_lli.next_lli = (uint32_t) & (timer_dma_lli); + timer_dma_lli.control = GPDMA_CCONTROL_TRANSFERSIZE(2) | + GPDMA_CCONTROL_SBSIZE(0) // 1 + | GPDMA_CCONTROL_DBSIZE(0) // 1 + | GPDMA_CCONTROL_SWIDTH(2) // 32-bit word + | GPDMA_CCONTROL_DWIDTH(2) // 32-bit word + | GPDMA_CCONTROL_S(0) // AHB Master 0 + | GPDMA_CCONTROL_D(1) // AHB Master 1 + | GPDMA_CCONTROL_SI(1) // increment source + | GPDMA_CCONTROL_DI(0) // do not increment destination + | GPDMA_CCONTROL_PROT1(0) // user mode + | GPDMA_CCONTROL_PROT2(0) // not bufferable + | GPDMA_CCONTROL_PROT3(0) // not cacheable + | GPDMA_CCONTROL_I(0); // interrupt disabled + gpdma_controller_enable(); + GPDMA_C0SRCADDR = timer_dma_lli.src; + GPDMA_C0DESTADDR = timer_dma_lli.dest; + GPDMA_C0LLI = timer_dma_lli.next_lli; + GPDMA_C0CONTROL = timer_dma_lli.control; + GPDMA_C0CONFIG = GPDMA_CCONFIG_DESTPERIPHERAL(0x7) // T3_MAT0 + | GPDMA_CCONFIG_FLOWCNTRL(1) // memory-to-peripheral + | GPDMA_CCONFIG_H(0); // do not halt + gpdma_channel_enable(0); + + /* start counting */ + timer_reset(TIMER0); + timer_reset(TIMER3); + timer_enable_counter(TIMER0); + timer_enable_counter(TIMER3); +} + +uint32_t clkin_frequency(void) +{ + return TIMER0_CR3 * (1000 / MEASUREMENT_WINDOW_MS); +}; diff --git a/firmware/common/clkin.h b/firmware/common/clkin.h new file mode 100644 index 00000000..2f2fa274 --- /dev/null +++ b/firmware/common/clkin.h @@ -0,0 +1,30 @@ +/* + * Copyright 2022 Great Scott Gadgets + * + * This file is part of HackRF. + * + * 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, 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; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __CLKIN_H__ +#define __CLKIN_H__ + +#include + +void clkin_detect_init(void); +uint32_t clkin_frequency(void); + +#endif //__CLKIN_H__ diff --git a/firmware/common/hackrf_core.c b/firmware/common/hackrf_core.c index bc0bb4b3..e0f4a880 100644 --- a/firmware/common/hackrf_core.c +++ b/firmware/common/hackrf_core.c @@ -727,7 +727,7 @@ void cpu_clock_init(void) CCU1_CLK_APB3_ADC1_CFG = 0; CCU1_CLK_APB3_CAN0_CFG = 0; CCU1_CLK_APB3_DAC_CFG = 0; - CCU1_CLK_M4_DMA_CFG = 0; + //CCU1_CLK_M4_DMA_CFG = 0; CCU1_CLK_M4_EMC_CFG = 0; CCU1_CLK_M4_EMCDIV_CFG = 0; CCU1_CLK_M4_ETHERNET_CFG = 0; @@ -737,10 +737,10 @@ void cpu_clock_init(void) // CCU1_CLK_M4_SCT_CFG = 0; CCU1_CLK_M4_SDIO_CFG = 0; CCU1_CLK_M4_SPIFI_CFG = 0; - CCU1_CLK_M4_TIMER0_CFG = 0; + //CCU1_CLK_M4_TIMER0_CFG = 0; CCU1_CLK_M4_TIMER1_CFG = 0; CCU1_CLK_M4_TIMER2_CFG = 0; - CCU1_CLK_M4_TIMER3_CFG = 0; + //CCU1_CLK_M4_TIMER3_CFG = 0; CCU1_CLK_M4_UART1_CFG = 0; CCU1_CLK_M4_USART0_CFG = 0; CCU1_CLK_M4_USART2_CFG = 0; diff --git a/firmware/hackrf-common.cmake b/firmware/hackrf-common.cmake index e7231923..ddc76a19 100644 --- a/firmware/hackrf-common.cmake +++ b/firmware/hackrf-common.cmake @@ -185,6 +185,8 @@ macro(DeclareTargets) ${PATH_HACKRF_FIRMWARE_COMMON}/hackrf_ui.c ${PATH_HACKRF_FIRMWARE_COMMON}/platform_detect.c ${PATH_HACKRF_FIRMWARE_COMMON}/firmware_info.c + ${PATH_HACKRF_FIRMWARE_COMMON}/clkin.c + ${PATH_HACKRF_FIRMWARE_COMMON}/gpdma.c ) if(BOARD STREQUAL "RAD1O") diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 56dd3ebc..893ecd53 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -55,6 +56,7 @@ #include "portapack.h" #include "hackrf_ui.h" #include "platform_detect.h" +#include "clkin.h" extern uint32_t __m0_start__; extern uint32_t __m0_end__; @@ -286,6 +288,8 @@ int main(void) } operacake_init(operacake_allow_gpio); + clkin_detect_init(); + while (true) { transceiver_request_t request;