start DAC and ADC io
This commit is contained in:
parent
32b96eaf9a
commit
5287366140
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue