From 7de27a2408a76ef16daf269d2a278a2bbba6e690 Mon Sep 17 00:00:00 2001 From: Peter McGoron Date: Wed, 27 Jul 2022 09:33:11 -0400 Subject: [PATCH] change converter code to drive new verilog --- software/src/io.c | 110 ++++++++++++---------------------------------- 1 file changed, 28 insertions(+), 82 deletions(-) diff --git a/software/src/io.c b/software/src/io.c index 630d085..944baec 100644 --- a/software/src/io.c +++ b/software/src/io.c @@ -8,113 +8,59 @@ LOG_MODULE_REGISTER(adc_dac_io); #define CSR_LOCATIONS #include "pin_io.h" +static int32_t +sign_extend(uint32_t n, unsigned wid) +{ + if (n >> (wid - 1)) + return (int32_t) (~((uint32_t) 0) & n); + else + return (int32_t) n; +} + int32_t adc_read(size_t num, unsigned wid) { - uint32_t buf = 0; - if (num >= ADC_MAX) { - LOG_ERR("Bad ADC %d\n", num); + LOG_ERR("adc_read got bad ADC %zd\n", num); k_fatal_halt(K_ERR_KERNEL_OOPS); } if (wid > 32) { - LOG_ERR("Bad ADC Width %u\n", wid); + LOG_ERR("adc_read got bad width %u\n", wid); k_fatal_halt(K_ERR_KERNEL_OOPS); } - /* SCK is set low because data is changed at the rising edge. */ - *adc_sck[num] = 0; *adc_conv[num] = 1; - - /* Wait setup time. - * The ADC sends an interrupt signal to notify the master that - * the ADC is ready to read out the data, but the evaluation boards - * do not expose that signal. This code relies on the maximum times - * listed in the datasheets. - * - * The ADCs have different maximum conversion times, so the longest - * one (LTC2328) is used. This number also includes t_BUSYLH. - */ k_sleep(K_NSEC(550)); + *adc_arm[num] = 1; *adc_conv[num] = 0; + // XXX: Guess + k_sleep(K_MSEC(40)); + while (!*adc_finished[num]); - for (int i = 0; i < wid; i++) { - k_sleep(K_NSEC(20)); - buf <<= 1; - buf |= *adc_sdo[num]; - - *adc_sck[num] = 1; - k_sleep(K_NSEC(20)); - *adc_sck[num] = 0; - } - - /* Sign extension. - * LT ADCs return twos-complement integers. They can be either positive - * or negative, and this is determined by the MSB (MSB = 1 means - * negative number). - * - * The ADCs do not send 32 bit integers, so the integers that are - * received must be sign extended. - * - * If a number is positive, no conversion is necessary. - * - * If a number is negative, then all bits beyond the original MSB - * must be set to 1. This can be done by ANDing the received number - * with all-bits-1. - * - * As an example, the negative 6-bit number - * 101101 - * can be sign extended to 8-bit by - * 11111111 - * & 00101101 - * ========== - * 11101101 - * (101101) - */ - if (buf >> wid) - return (int32_t) (~((uint32_t) 0) & buf); - else - return (int32_t) buf; + uint32_t buf = *adc_from_slave[num]; + *adc_arm[num] = 0; + return sign_extend(buf); } -#define DAC_SS(n, v) *dac_ctrl[(n)] |= (v & 1) << 2 -#define DAC_SCK(n, v) *dac_ctrl[(n)] |= (v & 1) << 1 -#define DAC_MOSI(n, v) *dac_ctrl[(n)] |= (v & 1) -#define DAC_MISO(n) *dac_miso[(n)] - -/* Thankfully we only have one type of DAC (for now). - * AD DACs are register-based devices. To write to a register, - * 1) Set SCK high. - * 2) Set SS high in software (SYNC is active-low), wait setup time. - * 3) Set SCK low. - * 4) Read MISO, write MOSI. - * 5) Set SCK high, wait setup time. -*/ uint32_t dac_write_raw(size_t n, uint32_t data) { - uint32_t r = 0; - DAC_SCK(n, 1); - DAC_SS(n, 1); - k_sleep(K_NSEC(10)); - if (n >= DAC_MAX) { LOG_ERR("dac_write_raw got bad ADC %d\n", n); k_fatal_halt(K_ERR_KERNEL_OOPS); } - for (int i = 0; i < 24; i++) { - DAC_SCK(n, 0); - DAC_MOSI(n, data >> 31 & 1); - k_sleep(K_NSEC(500)); - - r <<= 1; - data <<= 1; - r |= DAC_MISO(n) & 1; - DAC_SCK(n, 1); - k_sleep(K_NSEC(500)); - } + *dac_to_slave[n] = data; + *dac_ss[n] = 1; + k_sleep(K_NSEC(20)); + *dac_arm[n] = 1; + // XXX: Guess + k_sleep(K_MSEC(50)); + while (!*dac_finished[num]); + *dac_ss[n] = 0; + uint32_t r = *dac_from_slave[n]; + *dac_arm[n] = 0; return r; }