diff --git a/Makefile b/Makefile index 16f0ced..21bdbbc 100644 --- a/Makefile +++ b/Makefile @@ -78,6 +78,7 @@ SRC = main.c \ stm32f7xx_it.c \ system_stm32f7xx.c \ $(HALS)/stm32f7xx_hal.c \ + $(HALS)/stm32f7xx_hal_adc.c \ $(HALS)/stm32f7xx_hal_cortex.c \ $(HALS)/stm32f7xx_hal_rcc.c \ $(HALS)/stm32f7xx_hal_rcc_ex.c \ diff --git a/lib/l_test.c b/lib/l_test.c index 470ba13..448aa17 100644 --- a/lib/l_test.c +++ b/lib/l_test.c @@ -63,6 +63,12 @@ static int l_tp_dac(lua_State* L){ return 0; } +static int l_tp_adc_get(lua_State* L){ + int index = luaL_checkinteger(L, 1); + lua_pushnumber( L, TP_adc(index) ); + return 1; +} + // array of all the available functions static const struct luaL_Reg lib_test[]= { { "tp_power12" , l_tp_power12 } @@ -75,6 +81,7 @@ static const struct luaL_Reg lib_test[]= , { "tp_dacmux2" , l_tp_dac_mux_2 } , { "tp_jack_dir" , l_tp_jack_direction} , { "tp_dac" , l_tp_dac } + , { "tp_adc" , l_tp_adc_get } , { NULL , NULL } }; diff --git a/ll/adc.c b/ll/adc.c new file mode 100644 index 0000000..924bd25 --- /dev/null +++ b/ll/adc.c @@ -0,0 +1,159 @@ +#include "adc.h" + +#include +#include // HAL_Delay() + +#include "interrupts.h" + +#include "tp.h" + +static ADC_HandleTypeDef AdcHandle; +static ADC_ChannelConfTypeDef sConfig; +static uint32_t mchan = 0; // mux channel (for controlling tp module) + +#define ADC_CHANNELS 5 +#define ADC_SEQUENCE_LEN 8 +#define ADC_RAW_LEN (ADC_CHANNELS * ADC_SEQUENCE_LEN) +volatile uint32_t adc_raw[ADC_RAW_LEN]; + +static void start_conversion(int offset); + +void ADC_Init(void) +{ + AdcHandle.Instance = ADC1; + HAL_ADC_DeInit(&AdcHandle); + + AdcHandle.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV4; + AdcHandle.Init.Resolution = ADC_RESOLUTION_12B; + AdcHandle.Init.ScanConvMode = ADC_SCAN_ENABLE; + AdcHandle.Init.ContinuousConvMode = ENABLE; // i think disable + AdcHandle.Init.NbrOfConversion = 5; // scan all 5 chans on ADC1 + AdcHandle.Init.DiscontinuousConvMode = DISABLE; // i think enable + AdcHandle.Init.NbrOfDiscConversion = 1; + AdcHandle.Init.ExternalTrigConv = ADC_SOFTWARE_START; + AdcHandle.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; + AdcHandle.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T1_CC1; + AdcHandle.Init.DataAlign = ADC_DATAALIGN_RIGHT; + AdcHandle.Init.DMAContinuousRequests = ENABLE; + AdcHandle.Init.EOCSelection = ADC_EOC_SEQ_CONV; + + if( HAL_ADC_Init( &AdcHandle ) != HAL_OK ){ + printf("HAL_ADC_Init failed\n"); + } + + // Channel configuration + sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES; + sConfig.Offset = 0; + + sConfig.Channel = ADC_CHANNEL_0; + sConfig.Rank = 1; + if( HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK ) + printf("HAL_ADC_ConfigChannel failed\n"); + sConfig.Channel = ADC_CHANNEL_1; + sConfig.Rank = 2; + if( HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK ) + printf("HAL_ADC_ConfigChannel failed\n"); + sConfig.Channel = ADC_CHANNEL_2; + sConfig.Rank = 3; + if( HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK ) + printf("HAL_ADC_ConfigChannel failed\n"); + sConfig.Channel = ADC_CHANNEL_3; + sConfig.Rank = 4; + if( HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK ) + printf("HAL_ADC_ConfigChannel failed\n"); + sConfig.Channel = ADC_CHANNEL_4; + sConfig.Rank = 5; + if( HAL_ADC_ConfigChannel(&AdcHandle, &sConfig) != HAL_OK ) + printf("HAL_ADC_ConfigChannel failed\n"); + + start_conversion(0); +} + +static void start_conversion(int offset){ + TP_adc_mux_1(mchan); + if( HAL_ADC_Start_DMA( &AdcHandle + , (uint32_t*)&adc_raw[offset*ADC_CHANNELS] + , ADC_CHANNELS + ) != HAL_OK ){ + printf("HAL_ADC_Start_DMA failed, retrying..\n"); + // HAL_Delay(10); + if( HAL_ADC_Start_DMA( &AdcHandle + , (uint32_t*)&adc_raw[offset*ADC_CHANNELS] + , ADC_CHANNELS + ) != HAL_OK ){ + printf("HAL_ADC_Start_DMA failed again, ignoring\n"); + return; + } + } + // printf("conversion started\n\r"); +} + +static DMA_HandleTypeDef hdma_adc; +void HAL_ADC_MspInit(ADC_HandleTypeDef *hadc) +{ + GPIO_InitTypeDef gpio; + + __HAL_RCC_ADC1_CLK_ENABLE(); // just using ADC1 for now + // __HAL_RCC_ADC2_CLK_ENABLE(); + // __HAL_RCC_ADC3_CLK_ENABLE(); + __HAL_RCC_GPIOA_CLK_ENABLE(); + __HAL_RCC_DMA2_CLK_ENABLE(); ////////////////// check + gpio.Mode = GPIO_MODE_ANALOG; + gpio.Pull = GPIO_NOPULL; + + // ADC1,2,3 + gpio.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3 | GPIO_PIN_4; + HAL_GPIO_Init(GPIOA, &gpio); + + hdma_adc.Instance = DMA2_Stream4; /////////// check + + hdma_adc.Init.Channel = DMA_CHANNEL_0; /////////// check + hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY; + hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_adc.Init.MemInc = DMA_MINC_ENABLE; + hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + hdma_adc.Init.Mode = DMA_NORMAL; + hdma_adc.Init.Priority = DMA_PRIORITY_HIGH; + hdma_adc.Init.FIFOMode = DMA_FIFOMODE_DISABLE; + hdma_adc.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL; + hdma_adc.Init.MemBurst = DMA_MBURST_SINGLE; + hdma_adc.Init.PeriphBurst = DMA_PBURST_SINGLE; + + HAL_DMA_DeInit(&hdma_adc); + HAL_DMA_Init(&hdma_adc); + + __HAL_LINKDMA(hadc, DMA_Handle, hdma_adc); + + // FIXME + // (+++) Configure the priority and enable the NVIC for the transfer complete + // interrupt on the two DMA Streams. The output stream should have higher + // priority than the input stream. + HAL_NVIC_SetPriority(DMA2_Stream4_IRQn, ADC_IRQPriority, 1); + HAL_NVIC_EnableIRQ(DMA2_Stream4_IRQn); +} + +// static float i12b = 1.0 / 4096.0; +float ADC_get(int chan){ // inversion & bipolar shaping + // return (2.0 * adc_raw[chan] * i12b) - 1.0; + return adc_raw[chan]; +} + + +//// private +void DMA2_Stream4_IRQHandler(void){ + HAL_DMA_IRQHandler(AdcHandle.DMA_Handle); +} + +void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle){ + // advance MUX + mchan++; + mchan &= 0x7; // wrap to 8 channels + + // start next conversion + start_conversion(mchan); + // printf("adc conv complete\n\r"); +} +void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc){ + printf("adc error\n\r"); +} diff --git a/ll/adc.h b/ll/adc.h new file mode 100644 index 0000000..904aa47 --- /dev/null +++ b/ll/adc.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +void ADC_Init(void); + +void ADC_process(void); // call from main loop? better to just run a DMA w/ mux switching + +float ADC_get(int chan); + +void DMA2_Stream4_IRQHandler(void); +void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* AdcHandle); +void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc); diff --git a/ll/tp.c b/ll/tp.c index 12e3c5a..306d4cc 100644 --- a/ll/tp.c +++ b/ll/tp.c @@ -271,3 +271,98 @@ void TP_adc_mux_1(int chan){ void TP_dac(int chan, float value){ dac108_send(chan-1, value); } + +#include "adc.h" +static const int adc_lookup[] = { + 5, // adc0 = jack + 37, // adc1 + 32, + 27, + 22, + 18, + 13, + 8, + 3, + 38, + 33, + 28, + 23, + 19, + 14, + 9, + 4, + 39, + 34, + 29, + 24, + 20, + 15, + 10, + 5, + 40, + 35, + 30, + 25, // adc28 +// TODO allow string lookup for these + 0, // 29 = +i_DUT // 1.1107 + 5, // 30 = -i_DUT // 0.550 + 10, // 31 = +i_PTC // 1.107 + 15, // 32 = -i_PTC // 0.183 + 20, // 33 = +12V // 2.4 + 25 // 34 = -12V // 2.42 +}; +float TP_adc(int chan){ + // TODO map requested channel to memory-channel (many holes in the adc array) + if(chan<0 || chan > 34){ + return -6.66; // BAD CHANNEL + } else if(chan >= 29){ // power channel + float a = ADC_get(adc_lookup[chan]); // lua is 1-based + // TODO convert to human-readable form + return a; + } else { // regular channel + return ADC_get(adc_lookup[chan]); // lua is 1-based + } +} + +/* PIN MAPPINGS for ADC buffer + +1 +CURRENT_DUT (internal TP + DUT consumption) +6 -CURRENT_DUT (internal TP + DUT consumption) +11 +CURRENT_PTC (Vdrop across PTC) +16 -CURRENT_PTC (Vdrop across PTC) +21 +12V (+2v4 scaled) -> actual output voltage (check for droop) +26 -12V (+2v4 scaled) -> actual output voltage (check for droop) + +22 ADC4 +27 ADC3 +32 ADC2 +37 ADC1 + +3 ADC8 +8 ADC7 +13 ADC6 +18 ADC5 +23 ADC12 +28 ADC11 +33 ADC10 +38 ADC9 + +4 ADC16 +9 ADC15 +14 ADC14 +19 ADC13 +24 ADC20 +29 ADC19 +34 ADC18 +39 ADC17 + +5 ADC24 / IN JACK +10 ADC23 +15 ADC22 +20 ADC21 +25 ADC28 +30 ADC27 +35 ADC26 +40 ADC25 + +*/ diff --git a/ll/tp.h b/ll/tp.h index b7ca65c..7e0a593 100644 --- a/ll/tp.h +++ b/ll/tp.h @@ -35,3 +35,4 @@ int TP_cherry_state(int index); ///////////////////////////////// // read dynamically +float TP_adc(int chan); diff --git a/main.c b/main.c index a4b2c08..3dbdb49 100755 --- a/main.c +++ b/main.c @@ -21,6 +21,7 @@ #include "ll/tp.h" // test platform specifics #include "ll/dac108.h" +#include "ll/adc.h" int main(void) @@ -49,6 +50,8 @@ int main(void) // but not required until working on TS. // IO_Start(); // must start IO before running lua init() script + ADC_Init(); + events_init(); Metro_Init( max_timers-2 ); // reserve 2 timers for USB & ADC clock_init( 100 ); // TODO how to pass it the timer?