diff --git a/SHAL/Include/Peripheral/ADC/Reg/SHAL_ADC_REG_L432KC.h b/SHAL/Include/Peripheral/ADC/Reg/SHAL_ADC_REG_L432KC.h index 05befeb..847d28c 100644 --- a/SHAL/Include/Peripheral/ADC/Reg/SHAL_ADC_REG_L432KC.h +++ b/SHAL/Include/Peripheral/ADC/Reg/SHAL_ADC_REG_L432KC.h @@ -83,14 +83,14 @@ static inline SHAL_ADC_Control_Reg getADCControlReg(ADC_Key key) { static inline SHAL_ADC_Config_Reg getADCConfigReg(ADC_Key key) { - SHAL_ADC_Config_Reg res = {nullptr, ADC_CFGR_CONT, ADC_CFGR_RES_Pos, ADC_CFGR_ALIGN_Pos}; + SHAL_ADC_Config_Reg res = {nullptr, ADC_CFGR_CONT, ADC_CFGR_RES_Pos, ADC_CFGR_ALIGN_Pos, ADC_CFGR_CONT_Msk}; res.reg = &(ADC_TABLE[static_cast(key)]->CFGR); return res; } static inline SHAL_ADC_ISR_Reg getADCISRReg(ADC_Key key){ - SHAL_ADC_ISR_Reg res = {nullptr, ADC_ISR_EOC, ADC_ISR_EOS, ADC_ISR_ADRDY}; + SHAL_ADC_ISR_Reg res = {nullptr, ADC_ISR_EOC, ADC_ISR_EOS, ADC_ISR_ADRDY, ADC_ISR_OVR}; res.reg = &(ADC_TABLE[static_cast(key)]->ISR); return res; diff --git a/SHAL/Include/Peripheral/ADC/SHAL_ADC_TYPES.h b/SHAL/Include/Peripheral/ADC/SHAL_ADC_TYPES.h index 88b92d9..f9d7f70 100644 --- a/SHAL/Include/Peripheral/ADC/SHAL_ADC_TYPES.h +++ b/SHAL/Include/Peripheral/ADC/SHAL_ADC_TYPES.h @@ -39,6 +39,7 @@ struct SHAL_ADC_Config_Reg { uint32_t resolution_offset; uint32_t alignment_offset; + uint32_t continuous_mode_mask; }; //Register for all ADC data @@ -53,6 +54,7 @@ struct SHAL_ADC_ISR_Reg { uint32_t end_of_conversion_mask; uint32_t end_of_sequence_mask; uint32_t ready_mask; + uint32_t overrun_mask; }; //Register controlling the clock source for the ADC diff --git a/SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_REG_L432KC.h b/SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_REG_L432KC.h index 67463e4..f27d994 100644 --- a/SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_REG_L432KC.h +++ b/SHAL/Include/Peripheral/GPIO/Reg/SHAL_GPIO_REG_L432KC.h @@ -17,15 +17,15 @@ //Build enum map of available SHAL_GPIO pins enum class GPIO_Key : uint8_t { - A0, - A1, - A2, - A3, - A4, - A5, - A6, - A7, - A8, + A0 = 0, + A1 = 1, + A2 = 2, + A3 = 3, + A4 = 4, + A5 = 5, + A6 = 6, + A7 = 7, + A8 = 8, A9, A10, A11, @@ -124,7 +124,7 @@ constexpr uint32_t getGPIOPortNumber(const GPIO_Key g){ static inline SHAL_GPIO_Mode_Register getGPIOModeRegister(const GPIO_Key key){ volatile uint32_t* reg = &GPIO_TABLE[static_cast(key) / 16]->MODER; - uint32_t offset = 2 * static_cast(key) % 16; + uint32_t offset = 2 * (static_cast(key) % 16); return {reg,offset}; } @@ -158,7 +158,7 @@ static inline SHAL_GPIO_Output_Type_Register getGPIOOutputTypeRegister(const GPI static inline SHAL_GPIO_Output_Data_Register getGPIOOutputDataRegister(const GPIO_Key key){ volatile uint32_t* reg = &GPIO_TABLE[static_cast(key) / 16]->ODR; - uint32_t offset = static_cast(key) % 16; + uint32_t offset = (static_cast(key) % 16); return {reg,offset}; } diff --git a/SHAL/Include/Peripheral/Timer/SHAL_TIM.h b/SHAL/Include/Peripheral/Timer/SHAL_TIM.h index b3774f9..41093a2 100644 --- a/SHAL/Include/Peripheral/Timer/SHAL_TIM.h +++ b/SHAL/Include/Peripheral/Timer/SHAL_TIM.h @@ -21,7 +21,7 @@ public: /// Initializes a timer /// \param prescaler The amount of times the base clock has to cycle before the timer adds one to the count /// \param autoReload The number of timer counts before the count is reset and IRQ is called - void init(uint32_t prescaler, uint32_t autoReload); + void init(uint16_t prescaler, uint16_t autoReload); //Starts the counter void start(); diff --git a/SHAL/Src/STM32L4XX/Peripheral/ADC/SHAL_ADC.cpp b/SHAL/Src/STM32L4XX/Peripheral/ADC/SHAL_ADC.cpp index 86b9dc8..088a0f6 100644 --- a/SHAL/Src/STM32L4XX/Peripheral/ADC/SHAL_ADC.cpp +++ b/SHAL/Src/STM32L4XX/Peripheral/ADC/SHAL_ADC.cpp @@ -72,29 +72,44 @@ SHAL_Result SHAL_ADC::calibrate() { } uint16_t SHAL_ADC::singleConvertSingle(SHAL_ADC_Channel channel, SHAL_ADC_SampleTime time) { + auto data_reg = getADCDataReg(m_ADCKey); + auto ISR_reg = getADCISRReg(m_ADCKey); + auto config_reg = getADCConfigReg(m_ADCKey); - auto data_reg = getADCDataReg(m_ADCKey); //Where our output will be stored + SHAL_clear_bitmask(config_reg.reg, config_reg.continuous_mode_mask); - auto sampleTimeReg = getADCChannelSamplingTimeRegister(m_ADCKey,channel); + auto sampleTimeReg = getADCChannelSamplingTimeRegister(m_ADCKey, channel); + SHAL_set_bits(sampleTimeReg.reg, 3, static_cast(time), sampleTimeReg.channel_offset); - SHAL_set_bits(sampleTimeReg.reg,3,static_cast(time),sampleTimeReg.channel_offset); //Set sample time register TODO un-hardcode bit width? + addADCChannelToSequence(channel, 0); + if(setADCSequenceAmount(1) == SHAL_Result::ERROR) { return 0; } - addADCChannelToSequence(channel,0); //Use index 0 to convert channel - if(setADCSequenceAmount(1) == SHAL_Result::ERROR){return 0;} //Since we're using single convert, convert 1 channel - - if(enable() != SHAL_Result::OKAY){ + if(enable() != SHAL_Result::OKAY) { return 0; } - startConversion(); //Start ADC conversion - - auto ISR_reg = getADCISRReg(m_ADCKey); - - if(!SHAL_WAIT_FOR_CONDITION_US(((*ISR_reg.reg & ISR_reg.end_of_sequence_mask) != 0),500)){ //Wait for conversion - return 0; //Failed + // CRITICAL: Clear ALL relevant flags before starting + SHAL_apply_bitmask(ISR_reg.reg, ISR_reg.end_of_sequence_mask); + SHAL_apply_bitmask(ISR_reg.reg, ISR_reg.end_of_conversion_mask); + if(ISR_reg.overrun_mask) { + SHAL_apply_bitmask(ISR_reg.reg, ISR_reg.overrun_mask); } - return *data_reg.reg; + volatile uint16_t dummy = *data_reg.reg; + (void)dummy; + + startConversion(); + + if(!SHAL_WAIT_FOR_CONDITION_US(((*ISR_reg.reg & ISR_reg.end_of_conversion_mask) != 0), 2000)) { + return 0; + } + + uint16_t result = *data_reg.reg; + + SHAL_apply_bitmask(ISR_reg.reg, ISR_reg.end_of_conversion_mask); + SHAL_apply_bitmask(ISR_reg.reg, ISR_reg.end_of_sequence_mask); + + return result; } SHAL_Result SHAL_ADC::multiConvertSingle(SHAL_ADC_Channel* channels, const int numChannels, uint16_t* result, SHAL_ADC_SampleTime time) { @@ -259,27 +274,23 @@ SHAL_Result SHAL_ADC::setADCSequenceAmount(uint32_t amount) { } SHAL_Result SHAL_ADC::addADCChannelToSequence(SHAL_ADC_Channel channel, uint32_t index) { - - if(!isValid()){return SHAL_Result::ERROR;} + if(!isValid()) { return SHAL_Result::ERROR; } auto sequenceRegisters = getADCSequenceRegisters(m_ADCKey); - auto channelNum = static_cast(channel); - uint32_t bitSection = (index + 1) % 5; //Need a new variable since SQR1 has its data bits shifted up by one section to make room for the L section + uint32_t bitSection = (index + 1) % 5; uint32_t sequenceRegNumber = (index + 1) / 5; volatile uint32_t* sequenceReg = sequenceRegisters.regs[sequenceRegNumber]; uint32_t bitSectionOffset = sequenceRegisters.offsets[bitSection]; - if(sequenceRegNumber != 0){ - *sequenceReg = 0; //Clear previous conversions - } - else{ - *sequenceReg &= 0x0000000F; - } + // Clear only the specific 5 bits we're setting, not the entire register + uint32_t clearMask = ~(0x1F << bitSectionOffset); + *sequenceReg &= clearMask; - SHAL_set_bits(sequenceReg,5,channelNum,bitSectionOffset); + // Set the new channel number + *sequenceReg |= (channelNum << bitSectionOffset); return SHAL_Result::OKAY; } diff --git a/SHAL/Src/STM32L4XX/Peripheral/Timer/SHAL_TIM.cpp b/SHAL/Src/STM32L4XX/Peripheral/Timer/SHAL_TIM.cpp index c3b192d..99631e0 100644 --- a/SHAL/Src/STM32L4XX/Peripheral/Timer/SHAL_TIM.cpp +++ b/SHAL/Src/STM32L4XX/Peripheral/Timer/SHAL_TIM.cpp @@ -50,7 +50,7 @@ void Timer::enableInterrupt() { NVIC_EnableIRQ(getTimerIRQn(m_key)); //Enable the IRQn in the NVIC } -void Timer::init(uint32_t prescaler, uint32_t autoReload) { +void Timer::init(uint16_t prescaler, uint16_t autoReload) { SHAL_TIM_RCC_Register rcc = getTimerRCC(m_key); SHAL_apply_bitmask(rcc.reg,rcc.enable_mask); diff --git a/SHAL/Src/main.cpp b/SHAL/Src/main.cpp index 0a9e1a2..73733fe 100644 --- a/SHAL/Src/main.cpp +++ b/SHAL/Src/main.cpp @@ -2,25 +2,28 @@ #include "SHAL.h" -#define NUM_CHANNELS 8 +#define NUM_CHANNELS 6 +// Physical order on right-side header: A0, A1, A3, A4, A5, A6, A7 SHAL_ADC_Channel channels[NUM_CHANNELS] = { SHAL_ADC_Channel::CH5, SHAL_ADC_Channel::CH6, SHAL_ADC_Channel::CH8, SHAL_ADC_Channel::CH9, SHAL_ADC_Channel::CH10, - SHAL_ADC_Channel::CH11, SHAL_ADC_Channel::CH12, - SHAL_ADC_Channel::CH7 }; -uint16_t vals[NUM_CHANNELS] = {0,0,0,0,0,0,0,0}; +bool isDeviceOn = false; +bool shouldToggleDeviceState = true; +bool shouldCheckSensorThresholds = true; + +uint16_t vals[NUM_CHANNELS] = {0,0,0,0,0,0}; uint8_t currentSensor = 0; bool isAlarmBeeping = false; -uint16_t sensorThresholds[NUM_CHANNELS]; +uint16_t sensorThresholds[NUM_CHANNELS] = {0,0,0,0,0,0}; int buzzer_beepCount = 0; bool isBeepingForCalibration = false; @@ -39,7 +42,9 @@ void getSensorData(){ if(currentSensor == (NUM_CHANNELS - 1) && currentCycle == cyclesPerPrint - 1){ char buff[125]; - sprintf(buff, "5:%d,6:%d,8:%d,9:%d,10:%d,11:%d,12:%d,7:%d\r\n", vals[0],vals[1],vals[2],vals[3],vals[4],vals[5],vals[6],vals[7]); + // Print in the same order as the channels[] array (physical order) + sprintf(buff, "A0:%u,A1:%u,A3:%u,A4:%u,A5:%u,A6:%u\r\n", + vals[0], vals[1], vals[2], vals[3], vals[4], vals[5]); SHAL_UART2.sendString(buff); } @@ -49,7 +54,9 @@ void getSensorData(){ } void startBeeping(){ - SHAL_TIM6.init(4000000,400); //PWM switcher - standard error beeping rate + + SHAL_TIM6.setPrescaler(4000); + SHAL_TIM6.setARR(200); SHAL_TIM6.start(); } @@ -63,60 +70,63 @@ void stopBeeping(){ void checkSensorThresholds(){ - //bool sensorsRequirementsTemp = areSensorRequirementsMetCurrent; TODO uncomment all of this + bool localFlag = true; - /* for(int i = 0; i < NUM_CHANNELS; i++){ if(vals[i] < sensorThresholds[i]){ - areSensorRequirementsMetCurrent = false; //All sensors must be valid - - if(sensorsRequirementsTemp){ //Requirements were met before and aren't now, so start beeping timer - SHAL_TIM15.start(); - PIN(B5).setHigh(); - } - + areSensorRequirementsMetCurrent = false; //Conditions not met + localFlag = false; break; } } - - if(areSensorRequirementsMetCurrent){ - SHAL_TIM15.stop(); - stopBeeping(); - } - */ - - //Copied from loop TODO remove this once real functionality is implemented - if(!areSensorRequirementsMetCurrent){ - - if(areSensorRequirementsMetPrevious) { - PIN(B5).setHigh(); - SHAL_TIM15.start(); - } + if(localFlag){ + areSensorRequirementsMetCurrent = true; } - //-------------------------------------------------------------------------------- - else{ - PIN(B5).setLow(); - - if(!areSensorRequirementsMetPrevious) { //Transition from not met -> met + if(areSensorRequirementsMetCurrent){ + if(!areSensorRequirementsMetPrevious){ + SHAL_TIM1.stop(); + SHAL_TIM6.stop(); SHAL_TIM15.stop(); + PIN(A9).setLow(); stopBeeping(); } } + else{ + if(areSensorRequirementsMetPrevious){ + SHAL_TIM15.start(); + PIN(A9).setHigh(); + } + } + areSensorRequirementsMetPrevious = areSensorRequirementsMetCurrent; } void calibrateThresholds(){ - for(int i = 0; i < 6; i++){ - uint16_t sensorVal = SHAL_ADC1.singleConvertSingle(channels[currentSensor]); - sensorThresholds[i] = (sensorVal / 5) * 4; + // Read every channel once and set threshold to 80% of reading + for(int i = 0; i < NUM_CHANNELS; i++){ + uint16_t sensorVal = vals[i]; + + if(sensorVal < 50){ + sensorVal = 0; + } + else{ + sensorVal = sensorVal - 50; + } + sensorThresholds[i] = sensorVal; } + + char buff[125]; + // Print in the same order as the channels[] array (physical order) + sprintf(buff, "Thresholds calibrated to: A0:%u,A1:%u,A3:%u,A4:%u,A5:%u,A6:%u\r\n", + sensorThresholds[0], sensorThresholds[1], sensorThresholds[2], sensorThresholds[3], sensorThresholds[4], sensorThresholds[5]); + SHAL_UART2.sendString(buff); } void PWMToggle(){ //Flash light - PIN(B5).toggle(); + PIN(A9).toggle(); SHAL_TIM15.stop(); //Stop timer for allowed time off sensors @@ -125,7 +135,9 @@ void PWMToggle(){ buzzer_beepCount = 0; SHAL_TIM6.stop(); //Reset timer 6 SHAL_TIM1.stop(); //Stop buzzer - SHAL_TIM6.init(4000000,400); + + SHAL_TIM6.setPrescaler(4000); + SHAL_TIM6.setARR(400); } if(!isAlarmBeeping){ @@ -140,7 +152,7 @@ void PWMToggle(){ void buttonHoldCallback(){ - PIN(B5).toggle(); + shouldCheckSensorThresholds = false; //Dont check sensor thresholds yet, ensure that calibration beep happens SHAL_TIM7.stop(); //Stop this timer @@ -149,87 +161,104 @@ void buttonHoldCallback(){ buzzer_beepCount = 0; isBeepingForCalibration = true; - SHAL_TIM6.init(4000000,80); + SHAL_TIM6.init(4000,50); SHAL_TIM6.start(); calibrateThresholds(); SHAL_TIM1.start(); SHAL_TIM2.start(); //Restart value checks + + shouldToggleDeviceState = false; + shouldCheckSensorThresholds = true; } int main() { SHAL_init(); - SHAL_UART2.init(UART_Pair_Key::Tx2A2_Rx2A3); - SHAL_UART2.begin(115200); + //SHAL_UART2.init(UART_Pair_Key::Tx2A2_Rx2A3); + //SHAL_UART2.begin(115200); PIN(A0).setPinMode(PinMode::ANALOG_MODE); PIN(A1).setPinMode(PinMode::ANALOG_MODE); - //PIN(A2).setPinMode(PinMode::ANALOG_MODE); - //PIN(A3).setPinMode(PinMode::ANALOG_MODE); + PIN(A3).setPinMode(PinMode::ANALOG_MODE); PIN(A4).setPinMode(PinMode::ANALOG_MODE); PIN(A5).setPinMode(PinMode::ANALOG_MODE); PIN(A6).setPinMode(PinMode::ANALOG_MODE); PIN(A7).setPinMode(PinMode::ANALOG_MODE); - PIN(B5).setPinMode(PinMode::OUTPUT_MODE); - PIN(B6).setPinMode(PinMode::INPUT_MODE); + PIN(A9).setPinMode(PinMode::OUTPUT_MODE); + PIN(B0).setAlternateFunction(GPIO_Alternate_Function_Mapping::B0_TIM1CH2N); - SHAL_TIM2.init(4000000,400); + PIN(A8).setPinMode(PinMode::OUTPUT_MODE); + PIN(A8).setInternalResistor(InternalResistorType::NO_PULL); + + SHAL_TIM2.init(4000,200); SHAL_TIM2.setCallbackFunc(getSensorData); SHAL_TIM2.enableInterrupt(); SHAL_TIM2.start(); - PIN(B0).setAlternateFunction(GPIO_Alternate_Function_Mapping::B0_TIM1CH2N); - SHAL_TIM1.init(0,2400); //PWM signal SHAL_TIM1.setPWMMode(SHAL_Timer_Channel::CH2,SHAL_TIM_Output_Compare_Mode::PWMMode1,SHAL_Timer_Channel_Main_Output_Mode::Polarity_Normal,SHAL_Timer_Channel_Complimentary_Output_Mode::Polarity_Reversed); SHAL_TIM1.setPWMDutyCycle(900); - SHAL_TIM6.init(4000000,400); //PWM switcher + SHAL_TIM6.init(4000,500); //PWM switcher SHAL_TIM6.setCallbackFunc(PWMToggle); SHAL_TIM6.enableInterrupt(); - SHAL_TIM7.init(4000000,4500); + SHAL_TIM7.init(4000,3000); //Calibrate timer SHAL_TIM7.setCallbackFunc(buttonHoldCallback); SHAL_TIM7.enableInterrupt(); - SHAL_TIM15.init(4000000,5000); //1 second + SHAL_TIM15.init(4000,5000); //5 seconds SHAL_TIM15.setCallbackFunc(startBeeping); SHAL_TIM15.enableInterrupt(); + SHAL_UART2.sendString("Hello3\r\n"); + while (true) { //TODO set to use button for simulating off sensor, uncomment for real functionality if(PIN(B6).digitalRead() != 1){ - areSensorRequirementsMetCurrent = false; - /* - if(!prevIsCalibrateButtonHigh){ + if(prevIsCalibrateButtonHigh){ SHAL_TIM7.start(); } - prevIsCalibrateButtonHigh = true; - */ + prevIsCalibrateButtonHigh = false; + } else{ - areSensorRequirementsMetCurrent = true; + if(!prevIsCalibrateButtonHigh){ + if(shouldToggleDeviceState){ + if(!isDeviceOn){ //Turn device on + PIN(A8).setHigh(); + isDeviceOn = true; + } + else{ //Turn device off + PIN(A8).setLow(); + PIN(A9).setLow(); + isDeviceOn = false; + + areSensorRequirementsMetCurrent = true; + areSensorRequirementsMetPrevious = true; + + stopBeeping(); + } + + } + + shouldToggleDeviceState = true; - /* - if(prevIsCalibrateButtonHigh){ - //Button released SHAL_TIM7.stop(); } - prevIsCalibrateButtonHigh = false; - */ + prevIsCalibrateButtonHigh = true; } - checkSensorThresholds(); - - areSensorRequirementsMetPrevious = areSensorRequirementsMetCurrent; - + if(isDeviceOn && shouldCheckSensorThresholds){ + checkSensorThresholds(); + } } -} \ No newline at end of file +}