Add shared waveform processing, generation and firmware image support
This commit is contained in:
53
c/set-protocol/ports/stm32f407-wavegen/set_wave_f407.c
Normal file
53
c/set-protocol/ports/stm32f407-wavegen/set_wave_f407.c
Normal file
@@ -0,0 +1,53 @@
|
||||
#include "set_wave_f407.h"
|
||||
#include "stm32f4xx.h"
|
||||
static void stop(void *context) {
|
||||
unsigned limit=100000; (void)context;
|
||||
RCC->AHB1ENR|=RCC_AHB1ENR_GPIOAEN|RCC_AHB1ENR_DMA1EN;
|
||||
RCC->APB1ENR|=RCC_APB1ENR_DACEN|RCC_APB1ENR_TIM6EN;
|
||||
(void)RCC->APB1ENR;
|
||||
TIM6->CR1=0;
|
||||
DAC->CR&=~(DAC_CR_DMAEN1|DAC_CR_TEN1);
|
||||
DMA1_Stream5->CR&=~DMA_SxCR_EN;
|
||||
while((DMA1_Stream5->CR&DMA_SxCR_EN)&&--limit) {}
|
||||
/* Leave other DAC channel untouched. Channel 1 outputs zero on stop. */
|
||||
DAC->DHR12R1=0;
|
||||
DMA1->HIFCR=0xF40u;
|
||||
DAC->SR=DAC_SR_DMAUDR1;
|
||||
}
|
||||
static int start(void *context,const uint16_t *samples,size_t count,uint32_t rate) {
|
||||
set_wave_f407 *c=(set_wave_f407 *)context;
|
||||
uint32_t ticks,psc,arr; uintptr_t address=(uintptr_t)samples;
|
||||
if(!c||!rate||rate>SET_WAVE_MAX_RATE||count<2||count>SET_WAVE_MAX||c->timer_hz%rate
|
||||
||address<0x20000000u||address+count*2>0x20020000u) return 1;
|
||||
ticks=c->timer_hz/rate;
|
||||
for(psc=1;psc<=65536;++psc) if(ticks%psc==0&&ticks/psc<=65536) break;
|
||||
if(psc>65536||ticks<psc) return 1;
|
||||
arr=ticks/psc;
|
||||
stop(context);
|
||||
if(DMA1_Stream5->CR&DMA_SxCR_EN) return 1;
|
||||
GPIOA->MODER|=3u<<8;
|
||||
GPIOA->PUPDR&=~(3u<<8);
|
||||
TIM6->PSC=psc-1;TIM6->ARR=arr-1;TIM6->CNT=0;
|
||||
TIM6->CR2=0;TIM6->EGR=TIM_EGR_UG;TIM6->SR=0;
|
||||
TIM6->CR2=TIM_CR2_MMS_1; /* update -> TRGO */
|
||||
DMA1_Stream5->PAR=(uint32_t)&DAC->DHR12R1;
|
||||
DMA1_Stream5->M0AR=(uint32_t)samples;DMA1_Stream5->NDTR=(uint32_t)count;
|
||||
DMA1_Stream5->FCR=0;
|
||||
DMA1_Stream5->CR=(7u<<25)|DMA_SxCR_DIR_0|DMA_SxCR_MINC|DMA_SxCR_CIRC
|
||||
|DMA_SxCR_PSIZE_0|DMA_SxCR_MSIZE_0|DMA_SxCR_PL_1;
|
||||
/* Prime the previous period's last sample; DMA supplies the next value
|
||||
* after each trigger. Cyclic order is last,0,1,... with one priming tick. */
|
||||
DAC->CR&=~0xFFFFu;
|
||||
DAC->DHR12R1=samples[count-1];
|
||||
DAC->CR|=DAC_CR_EN1|DAC_CR_TEN1|DAC_CR_DMAEN1; /* TSEL1=0: TIM6 */
|
||||
DMA1_Stream5->CR|=DMA_SxCR_EN;
|
||||
TIM6->CR1=TIM_CR1_CEN;
|
||||
return 0;
|
||||
}
|
||||
set_wave_port set_wave_f407_port(set_wave_f407 *context) {
|
||||
set_wave_port port={context,start,stop};return port;
|
||||
}
|
||||
int set_wave_f407_fault(void) {
|
||||
return (DMA1->HISR&(DMA_HISR_TEIF5|DMA_HISR_DMEIF5|DMA_HISR_FEIF5))
|
||||
||(DAC->SR&DAC_SR_DMAUDR1);
|
||||
}
|
||||
12
c/set-protocol/ports/stm32f407-wavegen/set_wave_f407.h
Normal file
12
c/set-protocol/ports/stm32f407-wavegen/set_wave_f407.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef SET_WAVE_F407_H
|
||||
#define SET_WAVE_F407_H
|
||||
#include "../../include/set_wavegen.h"
|
||||
/* Owns PA4, DAC channel 1, TIM6 and DMA1 stream 5/channel 7.
|
||||
* timer_hz is TIM6 input clock (twice APB1 when APB1 prescaler !=1).
|
||||
* Rate: 1..SET_WAVE_MAX_RATE (1 MS/s), exact divisors of timer_hz only.
|
||||
* Context and sample buffer must outlive playback; buffer must be in SRAM. */
|
||||
typedef struct { uint32_t timer_hz; } set_wave_f407;
|
||||
set_wave_port set_wave_f407_port(set_wave_f407 *context);
|
||||
/* Nonzero on DMA error or DAC underrun; caller stops state on failure. */
|
||||
int set_wave_f407_fault(void);
|
||||
#endif
|
||||
37
c/set-protocol/ports/stm32g474-wavegen/set_wave_g474.c
Normal file
37
c/set-protocol/ports/stm32g474-wavegen/set_wave_g474.c
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "set_wave_g474.h"
|
||||
static void stop(void *context) {
|
||||
set_wave_g474 *c=(set_wave_g474 *)context;
|
||||
HAL_TIM_Base_Stop(c->timer);
|
||||
HAL_DAC_Stop_DMA(c->dac,DAC_CHANNEL_1);
|
||||
/* Disable triggering so zero is applied without another timer edge. */
|
||||
CLEAR_BIT(c->dac->Instance->CR,DAC_CR_TEN1);
|
||||
HAL_DAC_SetValue(c->dac,DAC_CHANNEL_1,DAC_ALIGN_12B_R,0);
|
||||
HAL_DAC_Start(c->dac,DAC_CHANNEL_1);
|
||||
}
|
||||
static int start(void *context,const uint16_t *samples,size_t count,uint32_t rate) {
|
||||
set_wave_g474 *c=(set_wave_g474 *)context;
|
||||
uint32_t ticks,psc; DMA_HandleTypeDef *dma;
|
||||
if(!c||!c->dac||!c->timer||c->dac->Instance!=DAC1||c->timer->Instance!=TIM6
|
||||
||!rate||rate>50000||count<2||count>SET_WAVE_MAX||c->timer_hz%rate) return 1;
|
||||
dma=c->dac->DMA_Handle1;
|
||||
if(!dma||dma->Init.Mode!=DMA_CIRCULAR||dma->Init.MemDataAlignment!=DMA_MDATAALIGN_HALFWORD
|
||||
||dma->Init.PeriphDataAlignment!=DMA_PDATAALIGN_HALFWORD
|
||||
||dma->Init.Request!=DMA_REQUEST_DAC1_CHANNEL1||dma->Init.MemInc!=DMA_MINC_ENABLE) return 1;
|
||||
ticks=c->timer_hz/rate;
|
||||
for(psc=1;psc<=65536;++psc) if(ticks%psc==0&&ticks/psc<=65536) break;
|
||||
if(psc>65536||ticks<psc) return 1;
|
||||
stop(context);
|
||||
__HAL_TIM_SET_PRESCALER(c->timer,psc-1);
|
||||
__HAL_TIM_SET_AUTORELOAD(c->timer,ticks/psc-1);
|
||||
__HAL_TIM_SET_COUNTER(c->timer,0);
|
||||
c->timer->Instance->EGR=TIM_EGR_UG;
|
||||
__HAL_TIM_CLEAR_FLAG(c->timer,TIM_FLAG_UPDATE);
|
||||
MODIFY_REG(c->dac->Instance->CR,DAC_CR_TSEL1|DAC_CR_TEN1,DAC_TRIGGER_T6_TRGO);
|
||||
HAL_DAC_SetValue(c->dac,DAC_CHANNEL_1,DAC_ALIGN_12B_R,samples[count-1]);
|
||||
if(HAL_DAC_Start_DMA(c->dac,DAC_CHANNEL_1,(uint32_t *)samples,(uint32_t)count,DAC_ALIGN_12B_R)!=HAL_OK) return 1;
|
||||
if(HAL_TIM_Base_Start(c->timer)!=HAL_OK) {stop(context);return 1;}
|
||||
return 0;
|
||||
}
|
||||
set_wave_port set_wave_g474_port(set_wave_g474 *context) {
|
||||
set_wave_port port={context,start,stop};return port;
|
||||
}
|
||||
10
c/set-protocol/ports/stm32g474-wavegen/set_wave_g474.h
Normal file
10
c/set-protocol/ports/stm32g474-wavegen/set_wave_g474.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef SET_WAVE_G474_H
|
||||
#define SET_WAVE_G474_H
|
||||
#include "stm32g4xx_hal.h"
|
||||
#include "../../include/set_wavegen.h"
|
||||
/* CubeMX owns initialization: DAC1 channel1 PA4, TIM6 TRGO_UPDATE,
|
||||
* DMA_REQUEST_DAC1_CHANNEL1, circular, halfword/halfword, memory increment.
|
||||
* Supply TIM6 input clock, not APB bus clock. DMA buffer in SRAM. */
|
||||
typedef struct { DAC_HandleTypeDef *dac; TIM_HandleTypeDef *timer; uint32_t timer_hz; } set_wave_g474;
|
||||
set_wave_port set_wave_g474_port(set_wave_g474 *context);
|
||||
#endif
|
||||
Reference in New Issue
Block a user