start DAC and ADC io

This commit is contained in:
Peter McGoron 2022-07-13 15:36:36 -04:00
parent 32b96eaf9a
commit 5287366140
1 changed files with 119 additions and 0 deletions

119
software/src/io.c Normal file
View File

@ -0,0 +1,119 @@
#include <zephyr/kernel.h>
#include "pin_io.h"
/* LT ADCs work like this:
* 1) Send CONV signal high
* 2) wait for conversion to happen
* 3) read in from output (change on rising edge, read on lower)
* The evaluation boards do not give access to the BUSY signal, so this
* contoller cannot be interrupt driven. This is probably a blessing
* in disguise because it's easier for me to write blocking code :-)
*/
struct adc_timing {
unsigned conv_time;
unsigned wid;
};
enum adc_types {
LT2380_24,
LT2328_16,
LT2328_18,
ADC_TYPES_LEN
};
uint32_t
adc_read(int num, enum adc_types ty)
{
uint32_t r = 0;
// TODO
static const struct time[ADC_TYPES_LEN] = {
[LT2380_24] = {0},
[LT2328_16] = {0},
[LT2328_18] = {0}
};
if (ty < 0 || ty >= ADC_TYPES_LEN) {
LOG_ERROR("adc_read got unknown ADC type\n");
k_fatal_halt(K_ERR_KERNEL_OOPS);
}
if (num < 0 || num >= ADC_MAX) {
LOG_ERROR("Bad ADC %d\n", num);
k_fatal_halt(K_ERR_KERNEL_OOPS);
}
*adc_sck[num] = 0;
*adc_conv[num] = 1;
k_sleep(K_NSEC(T_CONV + T_DSOBUSYL));
*adc_conv[num] = 0;
for (int i = 0; i < time[ty].wid; i++) {
r <<= 1;
r |= *adc_sdo[num];
*adc_sck[num] = 1;
/* 1 millisecond -> 1 MHz */
k_sleep(K_NSEC(500));
*adc_sck[num] = 0;
}
return r;
}
#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(int n, uint32_t data)
{
uint32_t r = 0;
DAC_SCK(n, 1);
DAC_SS(n, 1);
k_sleep(K_NSEC(10));
for (int i = 0; i < 20; 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));
}
return r;
}
void
dac_write_v(int n, uint32_t v)
{
dac_write_raw(n, (1 << 20) | (v & 0xFFFFF));
}
int
dac_init(int n)
{
/* Write to control register. */
const uint32_t msg =
(1 << 1) // RBUF
| (1 << 4) // Binary Offset
;
dac_write_raw(n, (1 << 21) | msg);
// Read from the control register
dac_write_raw(n, (1 << 21) | (1 << 23));
// Send NOP to read the returned data.
return dac_write_raw(n, 0) == msg;
}