This commit is contained in:
jaseg 2023-04-27 19:34:21 +02:00
parent d4cfddccaf
commit 646226a5ae

View file

@ -5,17 +5,23 @@
struct adc_state {
enum {
ADC_INIT_0 = 0,
ADC_RESET = 0,
ADC_RESET_RES,
ADC_INIT_0,
ADC_INIT_0_RES,
ADC_INIT_1,
ADC_INIT_1_RES,
ADC_INIT_2,
ADC_INIT_2_RES,
ADC_INIT_3,
ADC_INIT_4,
ADC_INIT_3_RES,
ADC_EMPTY_FIFO,
ADC_RUNNING = 0x42,
} state;
size_t response_bytes;
uint8_t txbuf[12];
uint8_t rxbuf[12];
uint16_t dma_ccr3;
uint32_t dma_ccr3;
int data[2];
} st_adc;
@ -112,60 +118,113 @@ void adc_sm(bool reset);
void adc_init(void);
static void adc_prepare_read_samples(void);
static void adc_schedule_read_reg(int addr);
static void adc_schedule_reset(void);
static void adc_schedule_null(void);
static void adc_schedule_write_reg(int addr, int value);
static void adc_setup_dma(size_t tx_bytes, size_t response_bytes);
void adc_sm(bool reset) {
GPIOA->BSRR = (1<<4);
if (reset) {
st_adc.state = ADC_INIT_0;
adc_schedule_read_reg(ADC_REG_ID);
TIM2->SMCR = TIM_SMCR_ETP | (7<<TIM_SMCR_TS_Pos) | (0<<TIM_SMCR_SMS_Pos);
TIM2->CR1 |= TIM_CR1_CEN;
st_adc.state = ADC_RESET;
adc_schedule_reset();
return;
}
switch (st_adc.state) {
case ADC_RESET:
TIM2->CR1 |= TIM_CR1_CEN;
adc_schedule_null();
st_adc.state = ADC_RESET_RES;
break;
case ADC_RESET_RES:
if (st_adc.rxbuf[0] != 0xff || st_adc.rxbuf[1] != 0x22) {
adc_sm(true);
} else {
TIM2->CR1 |= TIM_CR1_CEN;
adc_schedule_read_reg(ADC_REG_ID);
st_adc.state = ADC_INIT_0;
}
break;
case ADC_INIT_0:
TIM2->CR1 |= TIM_CR1_CEN;
adc_schedule_null();
st_adc.state = ADC_INIT_0_RES;
break;
case ADC_INIT_0_RES:
if (st_adc.rxbuf[0] != 0x22) {
adc_sm(true);
} else {
TIM2->CR1 |= TIM_CR1_CEN;
adc_schedule_write_reg(ADC_REG_CLOCK, ADC_CLOCK_CH1_EN | ADC_CLOCK_CH2_EN | ADC_CLOCK_OSR_8192 | ADC_CLOCK_PWR_HIRES);
st_adc.state = ADC_INIT_1;
}
break;
case ADC_INIT_1:
TIM2->CR1 |= TIM_CR1_CEN;
adc_schedule_null();
st_adc.state = ADC_INIT_1_RES;
break;
case ADC_INIT_1_RES:
if (adc_check_write_response(ADC_REG_CLOCK)) {
//asm volatile ("bkpt");
adc_sm(true);
} else {
TIM2->CR1 |= TIM_CR1_CEN;
adc_schedule_write_reg(ADC_REG_GAIN, ADC_GAIN1_PGAGAIN1_64 | ADC_GAIN1_PGAGAIN0_64);
st_adc.state = ADC_INIT_2;
}
break;
case ADC_INIT_2:
TIM2->CR1 |= TIM_CR1_CEN;
adc_schedule_null();
st_adc.state = ADC_INIT_2_RES;
break;
case ADC_INIT_2_RES:
if (adc_check_write_response(ADC_REG_GAIN)) {
//asm volatile ("bkpt");
adc_sm(true);
} else {
adc_schedule_write_reg(ADC_REG_CH0_CFG, ADC_CHn_CFG_DCBLK_DIS);
TIM2->CR1 |= TIM_CR1_CEN;
adc_schedule_write_reg(ADC_REG_MODE, (1<<ADC_MODE_WLENGTH_Pos) | ADC_MODE_TIMEOUT);
st_adc.state = ADC_INIT_3;
}
break;
case ADC_INIT_3:
if (adc_check_write_response(ADC_REG_CH0_CFG)) {
TIM2->CR1 |= TIM_CR1_CEN;
adc_schedule_null();
st_adc.state = ADC_INIT_3_RES;
break;
case ADC_INIT_3_RES:
if (adc_check_write_response(ADC_REG_MODE)) {
//asm volatile ("bkpt");
adc_sm(true);
} else {
adc_schedule_write_reg(ADC_REG_CH1_CFG, ADC_CHn_CFG_DCBLK_DIS);
st_adc.state = ADC_INIT_4;
TIM2->CR1 |= TIM_CR1_CEN;
adc_schedule_null();
st_adc.state = ADC_EMPTY_FIFO;
}
break;
case ADC_INIT_4:
if (adc_check_write_response(ADC_REG_CH1_CFG)) {
adc_sm(true);
case ADC_EMPTY_FIFO:
if (GPIOA->IDR & (1<<0)) { /* DRDY */
TIM2->CR1 |= TIM_CR1_CEN;
adc_schedule_null();
} else {
adc_prepare_read_samples();
st_adc.state = ADC_RUNNING;
adc_prepare_read_samples();
}
break;
@ -173,6 +232,7 @@ void adc_sm(bool reset) {
adc_prepare_read_samples();
break;
}
GPIOA->BRR = (1<<4);
}
void adc_init() {
@ -182,7 +242,7 @@ void adc_init() {
SPI1->CR1 |= SPI_CR1_SPE;
/* CH1 -> DRDY/TIM2-triggered start of conversion */
DMA1_Channel1->CCR = (1<<DMA_CCR_MSIZE_Pos) | (1<<DMA_CCR_PSIZE_Pos) | DMA_CCR_TEIE | DMA_CCR_DIR | DMA_CCR_CIRC;
DMA1_Channel1->CCR = (2<<DMA_CCR_MSIZE_Pos) | (2<<DMA_CCR_PSIZE_Pos) | DMA_CCR_TEIE | DMA_CCR_DIR | DMA_CCR_CIRC;
DMA1_Channel1->CMAR = (uint32_t)&st_adc.dma_ccr3;
DMA1_Channel1->CPAR = (uint32_t)&(DMA1_Channel3->CCR);
DMA1_Channel1->CNDTR = 1;
@ -197,11 +257,11 @@ void adc_init() {
TIM2->CR1 = TIM_CR1_OPM;
TIM2->CR2 = TIM_CR2_CCDS | (5<<TIM_CR2_MMS_Pos); /* set trigger output to OC2REF */
TIM2->SMCR = TIM_SMCR_ETP | (7<<TIM_SMCR_TS_Pos) | (6<<TIM_SMCR_SMS_Pos);
TIM2->SMCR = TIM_SMCR_ETP | (7<<TIM_SMCR_TS_Pos) | (0<<TIM_SMCR_SMS_Pos);
TIM2->DIER = TIM_DIER_CC3DE;
TIM2->CCMR1 = (0<<TIM_CCMR1_CC1S_Pos) | (7<<TIM_CCMR1_OC2M_Pos);
TIM2->CCER = TIM_CCER_CC1E;
TIM2->CCR2 = 1; /* ~CS pulse */
TIM2->CCMR2 = (0<<TIM_CCMR2_CC3S_Pos) | (7<<TIM_CCMR2_OC3M_Pos);
TIM2->CCER = TIM_CCER_CC3E;
TIM2->CCR3 = 8; /* ~CS pulse */
TIM2->ARR = 32; /* Time to TX DMA request */
st_adc.dma_ccr3 = DMA1_Channel3->CCR | DMA_CCR_EN;
@ -241,7 +301,7 @@ bool adc_check_write_response(size_t addr) {
return true;
}
if (st_adc.rxbuf[1] != (addr<<7)) {
if (st_adc.rxbuf[1] != ((addr<<7)&0xff)) {
return true;
}
@ -259,10 +319,11 @@ void adc_prepare_read_samples() {
DMA1_Channel2->CCR &= ~DMA_CCR_EN;
DMA1_Channel3->CCR &= ~DMA_CCR_EN;
DMA1_Channel2->CNDTR = 3*3; /* RX DMA */
DMA1_Channel3->CNDTR = 3*3; /* TX DMA */
DMA1_Channel2->CNDTR = 4*3; /* RX DMA */
DMA1_Channel3->CNDTR = 4*3; /* TX DMA */
DMA1_Channel1->CCR |= DMA_CCR_EN;
DMA1_Channel2->CCR |= DMA_CCR_EN;
TIM2->SMCR = TIM_SMCR_ETP | (7<<TIM_SMCR_TS_Pos) | (6<<TIM_SMCR_SMS_Pos);
}
void adc_schedule_read_reg(int addr) {
@ -272,6 +333,21 @@ void adc_schedule_read_reg(int addr) {
adc_setup_dma(3, 3);
}
void adc_schedule_reset() {
st_adc.txbuf[0] = 0x00;
st_adc.txbuf[1] = 0x11;
st_adc.txbuf[2] = 0;
adc_setup_dma(3, 3);
}
void adc_schedule_null() {
st_adc.txbuf[0] = 0;
st_adc.txbuf[1] = 0;
st_adc.txbuf[2] = 0;
adc_setup_dma(3, 3);
}
void adc_schedule_write_reg(int addr, int value) {
st_adc.txbuf[0] = 0x60 | (addr >> 1);
st_adc.txbuf[1] = (addr << 7);
@ -283,12 +359,12 @@ void adc_schedule_write_reg(int addr, int value) {
}
void adc_setup_dma(size_t tx_bytes, size_t response_bytes) {
for (size_t i=0; i<COUNT_OF(st_adc.txbuf); i++) {
for (size_t i=tx_bytes; i<COUNT_OF(st_adc.txbuf); i++) {
st_adc.txbuf[i] = 0;
}
size_t rx_len = st_adc.response_bytes + 2*3;
size_t tx_len = tx_bytes;
size_t rx_len = st_adc.response_bytes + 2*3 + 3;
size_t tx_len = tx_bytes + 3;
size_t len_bytes = rx_len > tx_len ? rx_len : tx_len;
st_adc.response_bytes = response_bytes;
@ -360,9 +436,10 @@ int main(void) {
* 15 - BT5
*/
GPIOA->MODER &= (~(CLEAR(15))); /* Clear JTAG TDI pin mode */
GPIOA->MODER |= IN(0) | OUT(1) | AF(2) | ANALOG(3) | IN(4) | AF(5) | AF(6) | AF(7) | AF(8) | AF(9) | AF(10) | IN(11)
GPIOA->MODER |= AF(0) | OUT(1) | AF(2) | ANALOG(3) | OUT(4) | AF(5) | AF(6) | AF(7) | AF(8) | AF(9) | AF(10) | IN(11)
| IN(12) | IN(13) | IN(14) | IN(15);
GPIOA->AFR[0] = AFRL( 2, 2) | /* TIM2 CH3 to ADC CS */
GPIOA->AFR[0] = AFRL( 0, 2) | /* TIM2 ETR */
AFRL( 2, 2) | /* TIM2 CH3 to ADC CS */
AFRL( 5, 0) | /* SPI1 SCK (to ADC) */
AFRL( 6, 0) | /* SPI1 HIPO */
AFRL( 7, 0); /* SPI1 HOPI */
@ -380,7 +457,8 @@ int main(void) {
(3<<GPIO_OSPEEDR_OSPEEDR10_Pos) |
(3<<GPIO_OSPEEDR_OSPEEDR13_Pos) |
(3<<GPIO_OSPEEDR_OSPEEDR14_Pos);
GPIOA->BSRR = (1<<1); /* ADC ~SYNC */
/* GPIOB:
* 0 - BT2
* 1 - BT1