diff --git a/stm32/aioc-fw/Src/ptt.h b/stm32/aioc-fw/Src/ptt.h index 77ed628..9dc89f1 100644 --- a/stm32/aioc-fw/Src/ptt.h +++ b/stm32/aioc-fw/Src/ptt.h @@ -5,6 +5,7 @@ #include "stm32f3xx_hal.h" #include "aioc.h" #include "led.h" +#include "settings.h" #define PTT_MASK_NONE 0x00 #define PTT_MASK_PTT1 0x01 @@ -14,31 +15,71 @@ #define PTT_PIN_PTT1 GPIO_PIN_1 #define PTT_PIN_PTT2 GPIO_PIN_0 -static inline void PTT_Control(uint8_t pttMask) +static inline void PTT_Assert(uint8_t pttMask) { - /* TODO: This way, both PTTs can only be asserted/deasserted simultaneously. - * Maybe better for future applications to have PTT1 and PTT2 controlled separately. */ __disable_irq(); if (pttMask & PTT_MASK_PTT1) { PTT_GPIO->BSRR = PTT_PIN_PTT1; LED_SET(1, 1); - } else { - PTT_GPIO->BRR = PTT_PIN_PTT1; - LED_SET(1, 0); + + /* Update debug register */ + settingsRegMap[SETTINGS_REG_DBGAUDIO0] |= SETTINGS_REG_DBGAIOC0_PTT1STATE_MASK; } if (pttMask & PTT_MASK_PTT2) { PTT_GPIO->BSRR = PTT_PIN_PTT2; LED_SET(0, 1); - } else { - PTT_GPIO->BRR = PTT_PIN_PTT2; - LED_SET(0, 0); + + /* Update debug register */ + settingsRegMap[SETTINGS_REG_DBGAUDIO0] |= SETTINGS_REG_DBGAIOC0_PTT2STATE_MASK; } __enable_irq(); } +static inline void PTT_Deassert(uint8_t pttMask) +{ + __disable_irq(); + + if (pttMask & PTT_MASK_PTT1) { + PTT_GPIO->BRR = PTT_PIN_PTT1; + LED_SET(1, 0); + + /* Update debug register */ + settingsRegMap[SETTINGS_REG_DBGAUDIO0] &= ~SETTINGS_REG_DBGAIOC0_PTT1STATE_MASK; + } + + if (pttMask & PTT_MASK_PTT2) { + PTT_GPIO->BRR = PTT_PIN_PTT2; + LED_SET(0, 0); + + /* Update debug register */ + settingsRegMap[SETTINGS_REG_DBGAUDIO0] &= ~SETTINGS_REG_DBGAIOC0_PTT2STATE_MASK; + } + + __enable_irq(); +} + +static inline void PTT_Control(uint8_t pttMask) +{ + /* TODO: Using this function, both PTTs can only be asserted/deasserted simultaneously. + * Switch to using fully event(edge) driven PTT assertion/deassertion using functions below */ + + if (pttMask & PTT_MASK_PTT1) { + PTT_Assert(PTT_MASK_PTT1); + } else { + PTT_Deassert(PTT_MASK_PTT1); + } + + if (pttMask & PTT_MASK_PTT2) { + PTT_Assert(PTT_MASK_PTT2); + } else { + PTT_Deassert(PTT_MASK_PTT2); + } + +} + static inline uint8_t PTT_Status(void) { uint32_t inputReg = PTT_GPIO->IDR; diff --git a/stm32/aioc-fw/Src/usb_audio.c b/stm32/aioc-fw/Src/usb_audio.c index 2993111..5a26dba 100644 --- a/stm32/aioc-fw/Src/usb_audio.c +++ b/stm32/aioc-fw/Src/usb_audio.c @@ -76,6 +76,7 @@ static void Timer_ADC_Init(void); static void Timer_DAC_Init(void); static void ADC_Init(void); static void DAC_Init(void); +static void Timeout_Timers_Init(void); //--------------------------------------------------------------------+ // Application Callback API Implementations @@ -107,6 +108,11 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * microphoneMute[channelNum] = ((audio_control_cur_1_t*) pBuff)->bCur; + /* Update debug register */ + settingsRegMap[SETTINGS_REG_DBGAUDIO0] = (settingsRegMap[SETTINGS_REG_DBGAUDIO0] & ~(SETTINGS_REG_DBGAUDIO0_RECMUTE0_MASK | SETTINGS_REG_DBGAUDIO0_RECMUTE1_MASK)) \ + | (microphoneMute[0] ? SETTINGS_REG_DBGAUDIO0_RECMUTE0_MASK : 0) \ + | (microphoneMute[1] ? SETTINGS_REG_DBGAUDIO0_RECMUTE1_MASK : 0); + TU_LOG2(" Set Mute: %d of channel: %u\r\n", microphoneMute[channelNum], channelNum); return true; @@ -119,6 +125,9 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * microphoneLinVolume[channelNum] = (microphoneLogVolume[channelNum] != 0x8000) ? (uint16_t) (65535 * pow(10, logVolume/20) + 0.5) : 0; /* log to linear with rounding */ + settingsRegMap[SETTINGS_REG_DBGAUDIO3] = ((((uint32_t) microphoneLinVolume[0]) << SETTINGS_REG_DBGAUDIO3_RECVOL0_OFFS) & SETTINGS_REG_DBGAUDIO3_RECVOL0_MASK) \ + | ((((uint32_t) microphoneLinVolume[1]) << SETTINGS_REG_DBGAUDIO3_RECVOL1_OFFS) & SETTINGS_REG_DBGAUDIO3_RECVOL1_MASK); + TU_LOG2(" Set Volume: %u.%u dB of channel: %u\r\n", microphoneLogVolume[channelNum] / 256, microphoneLogVolume[channelNum] % 256, channelNum); return true; @@ -139,6 +148,11 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * speakerMute[channelNum] = ((audio_control_cur_1_t*) pBuff)->bCur; + /* Update debug register */ + settingsRegMap[SETTINGS_REG_DBGAUDIO0] = (settingsRegMap[SETTINGS_REG_DBGAUDIO0] & ~(SETTINGS_REG_DBGAUDIO0_PLAYMUTE0_MASK | SETTINGS_REG_DBGAUDIO0_PLAYMUTE1_MASK)) \ + | (speakerMute[0] ? SETTINGS_REG_DBGAUDIO0_PLAYMUTE0_MASK : 0) \ + | (speakerMute[1] ? SETTINGS_REG_DBGAUDIO0_PLAYMUTE1_MASK : 0); + TU_LOG2(" Set Mute: %d of channel: %u\r\n", speakerMute[channelNum], channelNum); return true; @@ -152,6 +166,11 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * speakerLinVolume[channelNum] = (speakerLogVolume[channelNum] != 0x8000) ? (uint16_t) (65535 * pow(10, logVolume/20) + 0.5) : 0; /* log to linear with rounding */ + /* Update debug register */ + settingsRegMap[SETTINGS_REG_DBGAUDIO9] = ((((uint32_t) speakerLinVolume[0]) << SETTINGS_REG_DBGAUDIO9_PLAYVOL0_OFFS) & SETTINGS_REG_DBGAUDIO9_PLAYVOL0_MASK) \ + | ((((uint32_t) speakerLinVolume[1]) << SETTINGS_REG_DBGAUDIO9_PLAYVOL1_OFFS) & SETTINGS_REG_DBGAUDIO9_PLAYVOL1_MASK); + + TU_LOG2(" Set Volume: %u.%u dB of channel: %u\r\n", microphoneLogVolume[channelNum] / 256, microphoneLogVolume[channelNum] % 256, channelNum); return true; @@ -177,6 +196,9 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * Timer_ADC_Init(); + /* Update debug register */ + settingsRegMap[SETTINGS_REG_DBGAUDIO2] = (((uint32_t) microphoneSampleFreqCfg) << SETTINGS_REG_DBGAUDIO2_RECRATE_OFFS) & SETTINGS_REG_DBGAUDIO2_RECRATE_MASK; + return true; // Unknown/Unsupported control @@ -208,6 +230,9 @@ bool tud_audio_set_req_entity_cb(uint8_t rhport, tusb_control_request_t const * Timer_DAC_Init(); + /* Update debug register */ + settingsRegMap[SETTINGS_REG_DBGAUDIO8] = (((uint32_t) speakerSampleFreqCfg) << SETTINGS_REG_DBGAUDIO8_PLAYRATE_OFFS) & SETTINGS_REG_DBGAUDIO8_PLAYRATE_MASK; + return true; // Unknown/Unsupported control @@ -493,6 +518,10 @@ bool tud_audio_tx_done_pre_load_cb(uint8_t rhport, uint8_t itf, uint8_t ep_in, u /* Start ADC sampling as soon as device stacks starts loading data (will be a ZLP for first frame) */ NVIC_EnableIRQ(ADC1_2_IRQn); microphoneState = STATE_RUN; + + /* Update debug register */ + settingsRegMap[SETTINGS_REG_DBGAUDIO0] = (settingsRegMap[SETTINGS_REG_DBGAUDIO0] & ~SETTINGS_REG_DBGAUDIO0_RECSTATE_MASK) + | (((uint32_t) SETTINGS_REG_DBGAUDIO0_RECSTATE_RUN_ENUM) << SETTINGS_REG_DBGAUDIO0_RECSTATE_OFFS); } return true; @@ -513,6 +542,10 @@ bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, u /* Wait until whe are at buffer target fill level, then start DAC output */ speakerState = STATE_RUN; NVIC_EnableIRQ(TIM6_DAC1_IRQn); + + /* Update debug register */ + settingsRegMap[SETTINGS_REG_DBGAUDIO0] = (settingsRegMap[SETTINGS_REG_DBGAUDIO0] & ~SETTINGS_REG_DBGAUDIO0_PLAYSTATE_MASK) + | (((uint32_t) SETTINGS_REG_DBGAUDIO0_PLAYSTATE_RUN_ENUM) << SETTINGS_REG_DBGAUDIO0_PLAYSTATE_OFFS); } /* Initialize/override min/max/avg during startup buffering */ @@ -521,6 +554,11 @@ bool tud_audio_rx_done_post_read_cb(uint8_t rhport, uint16_t n_bytes_received, u speakerBufferLvlMax = count; } + /* Write to debug registers */ + settingsRegMap[SETTINGS_REG_DBGAUDIO10] = ((uint32_t) (speakerBufferLvlAvg >> 16) << SETTINGS_REG_DBGAUDIO10_PLAYBUFAVG_OFFS) & SETTINGS_REG_DBGAUDIO10_PLAYBUFAVG_MASK; + settingsRegMap[SETTINGS_REG_DBGAUDIO11] = ((uint32_t) speakerBufferLvlMin << SETTINGS_REG_DBGAUDIO11_PLAYBUFMIN_OFFS) & SETTINGS_REG_DBGAUDIO11_PLAYBUFMIN_MASK; + settingsRegMap[SETTINGS_REG_DBGAUDIO12] = ((uint32_t) speakerBufferLvlMax << SETTINGS_REG_DBGAUDIO12_PLAYBUFMAX_OFFS) & SETTINGS_REG_DBGAUDIO12_PLAYBUFMAX_MASK; + return true; } @@ -538,6 +576,13 @@ bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_reque if (alt == 1) { /* Microphone channel has been activated */ microphoneState = STATE_START; + + /* Update VCOS/VPTT timeouts */ + Timeout_Timers_Init(); + + /* Update debug register */ + settingsRegMap[SETTINGS_REG_DBGAUDIO0] = (settingsRegMap[SETTINGS_REG_DBGAUDIO0] & ~SETTINGS_REG_DBGAUDIO0_RECSTATE_MASK) + | (((uint32_t) SETTINGS_REG_DBGAUDIO0_RECSTATE_START_ENUM) << SETTINGS_REG_DBGAUDIO0_RECSTATE_OFFS); } break; @@ -545,6 +590,13 @@ bool tud_audio_set_itf_cb(uint8_t rhport, tusb_control_request_t const * p_reque if (alt == 1) { /* Speaker channel has been activated */ speakerState = STATE_START; + + /* Update VCOS/VPTT timeouts */ + Timeout_Timers_Init(); + + /* Update debug register */ + settingsRegMap[SETTINGS_REG_DBGAUDIO0] = (settingsRegMap[SETTINGS_REG_DBGAUDIO0] & ~SETTINGS_REG_DBGAUDIO0_PLAYSTATE_MASK) + | (((uint32_t) SETTINGS_REG_DBGAUDIO0_PLAYSTATE_START_ENUM) << SETTINGS_REG_DBGAUDIO0_PLAYSTATE_OFFS); } break; @@ -567,12 +619,20 @@ bool tud_audio_set_itf_close_EP_cb(uint8_t rhport, tusb_control_request_t const /* Microphone channel has been stopped */ NVIC_DisableIRQ(ADC1_2_IRQn); microphoneState = STATE_OFF; + + /* Update debug register */ + settingsRegMap[SETTINGS_REG_DBGAUDIO0] = (settingsRegMap[SETTINGS_REG_DBGAUDIO0] & ~SETTINGS_REG_DBGAUDIO0_RECSTATE_MASK) + | (((uint32_t) SETTINGS_REG_DBGAUDIO0_RECSTATE_OFF_ENUM) << SETTINGS_REG_DBGAUDIO0_RECSTATE_OFFS); break; case ITF_NUM_AUDIO_STREAMING_OUT: /* Speaker channel has been stopped */ NVIC_DisableIRQ(TIM6_DAC1_IRQn); speakerState = STATE_OFF; + + /* Update debug register */ + settingsRegMap[SETTINGS_REG_DBGAUDIO0] = (settingsRegMap[SETTINGS_REG_DBGAUDIO0] & ~SETTINGS_REG_DBGAUDIO0_PLAYSTATE_MASK) + | (((uint32_t) SETTINGS_REG_DBGAUDIO0_PLAYSTATE_OFF_ENUM) << SETTINGS_REG_DBGAUDIO0_PLAYSTATE_OFFS); break; default: @@ -638,6 +698,11 @@ TU_ATTR_FAST_FUNC void tud_audio_feedback_interval_isr(uint8_t func_id, uint32_t speakerFeedbackMin = feedback; speakerFeedbackMax = feedback; } + + /* Write to debug registers */ + settingsRegMap[SETTINGS_REG_DBGAUDIO13] = ((uint32_t) (speakerFeedbackAvg >> 16) << SETTINGS_REG_DBGAUDIO13_PLAYFBAVG_OFFS) & SETTINGS_REG_DBGAUDIO13_PLAYFBAVG_MASK; + settingsRegMap[SETTINGS_REG_DBGAUDIO14] = ((uint32_t) speakerFeedbackMin << SETTINGS_REG_DBGAUDIO14_PLAYFBMIN_OFFS) & SETTINGS_REG_DBGAUDIO14_PLAYFBMIN_MASK; + settingsRegMap[SETTINGS_REG_DBGAUDIO15] = ((uint32_t) speakerFeedbackMax << SETTINGS_REG_DBGAUDIO15_PLAYFBMAX_OFFS) & SETTINGS_REG_DBGAUDIO15_PLAYFBMAX_MASK; } void ADC1_2_IRQHandler (void) @@ -706,15 +771,29 @@ void TIM16_IRQHandler(void) /* If timer was not enabled previously, enable timer and assert PTT */ TIM16->CR1 = cr | TIM_CR1_CEN; + /* Update debug register */ + settingsRegMap[SETTINGS_REG_DBGAUDIO0] |= SETTINGS_REG_DBGAIOC0_VPTTSTATE_MASK; + + /* Assert enabled PTTs */ uint8_t pttMask = PTT_MASK_NONE; pttMask |= settingsRegMap[SETTINGS_REG_AIOC_IOMUX0] & SETTINGS_REG_AIOC_IOMUX0_PTT1SRC_VPTT_MASK ? PTT_MASK_PTT1 : 0; pttMask |= settingsRegMap[SETTINGS_REG_AIOC_IOMUX1] & SETTINGS_REG_AIOC_IOMUX1_PTT2SRC_VPTT_MASK ? PTT_MASK_PTT2 : 0; - PTT_Control(pttMask); + + PTT_Assert(pttMask); } } else if (flags & TIM_SR_CC1IF) { /* The idle timeout (without any action on the DAC) was reached. Disable timer and deassert PTT */ TIM16->CR1 &= ~TIM_CR1_CEN; - PTT_Control(PTT_MASK_NONE); + + /* Update debug register */ + settingsRegMap[SETTINGS_REG_DBGAUDIO0] &= ~SETTINGS_REG_DBGAIOC0_VPTTSTATE_MASK; + + /* Deassert enabled PTTs */ + uint8_t pttMask = PTT_MASK_NONE; + pttMask |= settingsRegMap[SETTINGS_REG_AIOC_IOMUX0] & SETTINGS_REG_AIOC_IOMUX0_PTT1SRC_VPTT_MASK ? PTT_MASK_PTT1 : 0; + pttMask |= settingsRegMap[SETTINGS_REG_AIOC_IOMUX1] & SETTINGS_REG_AIOC_IOMUX1_PTT2SRC_VPTT_MASK ? PTT_MASK_PTT2 : 0; + + PTT_Deassert(pttMask); } TIM16->SR = ~flags; @@ -731,11 +810,21 @@ void TIM17_IRQHandler(void) if (!(cr & TIM_CR1_CEN)) { /* If timer was not enabled previously, enable timer and notify host of COS */ TIM17->CR1 = cr | TIM_CR1_CEN; + + /* Update debug register */ + settingsRegMap[SETTINGS_REG_DBGAUDIO0] |= SETTINGS_REG_DBGAIOC0_VCOSSTATE_MASK; + + /* Set COS state */ COS_SetState(0x01); } } else if (flags & TIM_SR_CC1IF) { /* The idle timeout (without any action on the ADC) was reached. Disable timer and notify host */ TIM17->CR1 &= ~TIM_CR1_CEN; + + /* Update debug register */ + settingsRegMap[SETTINGS_REG_DBGAUDIO0] &= ~SETTINGS_REG_DBGAIOC0_VCOSSTATE_MASK; + + /* Set COS state */ COS_SetState(0x00); } @@ -886,12 +975,12 @@ static void Timeout_Timers_Init() /* TIM16 and TIM17 are timeout-counters for PTT and COS */ TIM16->CR1 = TIM_CLOCKDIVISION_DIV1 | TIM_COUNTERMODE_UP; - TIM16->PSC = timerFreq / 1000000 - 1; /* Microseconds counter */ + TIM16->PSC = timerFreq / 16000 - 1; /* 16 kHz counter */ TIM16->CCR1 = pttTimeout - 1; TIM16->DIER = TIM_DIER_UIE | TIM_DIER_CC1IE; TIM17->CR1 = TIM_CLOCKDIVISION_DIV1 | TIM_COUNTERMODE_UP; - TIM17->PSC = timerFreq / 1000000 - 1; /* Microseconds counter */ + TIM17->PSC = timerFreq / 16000 - 1; /* 16 kHz counter */ TIM17->CCR1 = cosTimeout - 1; TIM17->DIER = TIM_DIER_UIE | TIM_DIER_CC1IE;