-
Notifications
You must be signed in to change notification settings - Fork 0
/
dac.c
92 lines (77 loc) · 2.28 KB
/
dac.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include <libopencm3/lpc43xx/ssp.h>
#include <libopencm3/lpc43xx/scu.h>
#include <libopencm3/lpc43xx/cgu.h>
#include "dac.h"
#include "pin.h"
static uint32_t cmd_buffer[8];
static unsigned int ncmds;
static struct pin_t cs = { port : GPIO0, pin : GPIOPIN15 };
static struct pin_t nldac = { port : GPIO2, pin : GPIOPIN13 };
void fill_cmd_buffer(unsigned int n, struct dac_update_t *updates)
{
uint32_t *tmp = cmd_buffer;
if (n > 8) n = 8;
for (unsigned int i=0; i<n; i++)
tmp[i] = (updates[i].channel << 20) | (updates[i].value << 4);
tmp[n-1] |= 1<<25; // update all registers
ncmds = n;
}
void send_cmd_buffer() {
for (unsigned int i=0; i<ncmds; i++) {
pin_off(&cs);
uint32_t tmp = cmd_buffer[i];
for (int j=0; j<4; j++) {
ssp_transfer(SSP1_NUM, 0xff & (tmp >> 24));
tmp <<= 8;
while (!(SSP1_SR & SSP_SR_TNF));
}
while (!(SSP1_SR & SSP_SR_TFE));
pin_on(&cs);
}
ncmds = 0;
}
void set_dac(unsigned int n, struct dac_update_t *updates)
{
// TODO: Check for existing transaction
if (!(SSP1_SR & SSP_SR_TFE))
while (1);
fill_cmd_buffer(n, updates);
send_cmd_buffer();
}
void dac_init()
{
ncmds = 0;
pin_setup_output(&cs);
pin_setup_output(&nldac);
pin_off(&nldac);
pin_on(&cs);
/* use PLL1 as clock source */
CGU_BASE_SSP1_CLK =
CGU_BASE_SSP1_CLK_CLK_SEL(CGU_SRC_PLL1)
| CGU_BASE_SSP1_CLK_AUTOBLOCK(1);
// DAC specified up to 50MHz
// 204MHz / 4 == 51MHz
ssp_init(SSP1_NUM,
SSP_DATA_8BITS,
SSP_FRAME_SPI,
SSP_CPOL_0_CPHA_1,
0,
4,
SSP_MODE_NORMAL,
SSP_MASTER,
SSP_SLAVE_OUT_DISABLE);
scu_pinmux(P1_19, SCU_CONF_FUNCTION1 | SCU_SSP_IO); // SCK
scu_pinmux(P0_0, SCU_CONF_FUNCTION1 | SCU_SSP_IO); // MISO
scu_pinmux(P0_1, SCU_CONF_FUNCTION1 | SCU_SSP_IO); // MOSI
scu_pinmux(P1_20, SCU_CONF_FUNCTION0 | SCU_GPIO_NOPULL); // CS = GPIO0[15]
scu_pinmux(P5_4, SCU_CONF_FUNCTION0 | SCU_GPIO_NOPULL); // LDAC = GPIO2[13]
// Enable internal reference
cmd_buffer[0] = (1<<27) | 1;
ncmds = 1;
send_cmd_buffer();
}
void load_dac()
{
pin_on(&nldac);
pin_off(&nldac);
}