Kestrel Interface
Loading...
Searching...
No Matches
kest_fpga_io.c
Go to the documentation of this file.
1#include "kest_int.h"
2
3#ifndef PRINTLINES_ALLOWED
4#define PRINTLINES_ALLOWED 0
5#endif
6
7static const char *FNAME = "kest_fpga_io.c";
8
9#ifndef KEST_FPGA_SIMULATED
10#include <driver/spi_master.h>
11
12#define PIN_NUM_MISO 14
13#define PIN_NUM_MOSI 6
14#define PIN_NUM_CLK 5
15#define PIN_NUM_CS 4
16
17spi_device_handle_t spi_handle;
18#endif
19
21{
22 #ifndef KEST_FPGA_SIMULATED
23 esp_err_t ret;
24
25 spi_bus_config_t buscfg = {
26 .mosi_io_num = PIN_NUM_MOSI,
27 .miso_io_num = PIN_NUM_MISO,
28 .sclk_io_num = PIN_NUM_CLK,
29 .quadwp_io_num = -1,
30 .quadhd_io_num = -1,
31 .max_transfer_sz = 4096,
32 };
33
34 ret = spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO);
35 if (ret != ESP_OK)
36 return ERR_SPI_FAIL;
37
38 spi_device_interface_config_t devcfg = {
39 .clock_speed_hz = 1 * 1000 * 1000,
40 .mode = 0,
41 .spics_io_num = PIN_NUM_CS,
42 .queue_size = 4,
43 };
44
45 ret = spi_bus_add_device(SPI2_HOST, &devcfg, &spi_handle);
46 if (ret != ESP_OK)
47 return ERR_SPI_FAIL;
48
49 #endif
50 return NO_ERROR;
51}
52
53int kest_fpga_txrx(uint8_t *tx, uint8_t *rx, size_t len)
54{
55 #ifndef KEST_FPGA_SIMULATED
56 if (len == 0)
57 return 0;
58
59 spi_transaction_t t = {
60 .length = len * 8,
61 .tx_buffer = tx,
62 .rx_buffer = rx,
63 };
64
65 esp_err_t err = spi_device_transmit(spi_handle, &t);
66
67 #ifdef PRINT_SPI_BYTES
68 char print_buf[len * 10 + 1];
69 int buf_index = 0;
70 for (int i = 0; i < len; i++)
71 {
72 sprintf(&print_buf[buf_index], "SEND 0x%02x\n", tx[i]);
73 buf_index += 10;
74 }
75 print_buf[buf_index] = 0;
76 KEST_PRINTF("\n\n\n\n\n\n\n\n\n\n\n\n\nSPI send to FPGA (%d bytes):\n", len);
77 KEST_PRINTF(print_buf);
78
79 KEST_PRINTF("FPGA replied with\n");
80 buf_index = 0;
81 for (int i = 0; i < len; i++)
82 {
83 sprintf(&print_buf[buf_index], "RCVD 0x%02x\n", reply_buf[i]);
84 buf_index += 10;
85 }
86 print_buf[buf_index] = 0;
87 KEST_PRINTF(print_buf);
88 #endif
89
90 return (err == ESP_OK) ? NO_ERROR : ERR_SPI_FAIL;
91 #else
93 #endif
94}
95
96int kest_fpga_send_byte(uint8_t byte)
97{
98 return kest_fpga_txrx(&byte, NULL, 1);
99}
100
102{
103 uint8_t tx = 0;
104 uint8_t rx;
105 kest_fpga_txrx(&tx, &rx, 1);
106 return rx;
107}
108
110{
112
113 seq.buf = kest_alloc(sizeof(uint32_t) * KEST_FPGA_N_BLOCKS);
114 seq.len = 0;
115 seq.buf_len = (int)(sizeof(uint32_t) * KEST_FPGA_N_BLOCKS);
116 seq.buffer_owned = 0;
117
118 return seq;
119}
120
122{
123 if (batch.buf && !batch.buffer_owned) kest_free(batch.buf);
124}
125
127{
128 if (!seq)
129 return ERR_NULL_PTR;
130
131 if (seq->len >= seq->buf_len)
132 {
133 uint8_t *new_ptr = kest_realloc(seq->buf,(seq->buf_len * 2) * sizeof(uint8_t));
134
135 if (!new_ptr)
136 return ERR_ALLOC_FAIL;
137
138 seq->buf = new_ptr;
139 seq->buf_len *= 2;
140 }
141
142 seq->buf[seq->len++] = x;
143
144 return NO_ERROR;
145}
146
147
149{
150 uint8_t bytes[2];
151
152 bytes[0] = range_bits(x, 8, 8);
153 bytes[1] = range_bits(x, 8, 0);
154
155 int ret_val;
156
157 if ((ret_val = kest_fpga_batch_append(seq, bytes[0])) != NO_ERROR) return ret_val;
158 if ((ret_val = kest_fpga_batch_append(seq, bytes[1])) != NO_ERROR) return ret_val;
159
160 return ret_val;
161}
162
163
165{
166 uint8_t bytes[3];
167
168 bytes[0] = range_bits(x, 8, 16);
169 bytes[1] = range_bits(x, 8, 8);
170 bytes[2] = range_bits(x, 8, 0);
171
172 int ret_val;
173
174 if ((ret_val = kest_fpga_batch_append(seq, bytes[0])) != NO_ERROR) return ret_val;
175 if ((ret_val = kest_fpga_batch_append(seq, bytes[1])) != NO_ERROR) return ret_val;
176 if ((ret_val = kest_fpga_batch_append(seq, bytes[2])) != NO_ERROR) return ret_val;
177
178 return ret_val;
179}
180
182{
183 uint8_t bytes[4];
184
185 bytes[0] = range_bits(x, 8, 24);
186 bytes[1] = range_bits(x, 8, 16);
187 bytes[2] = range_bits(x, 8, 8);
188 bytes[3] = range_bits(x, 8, 0);
189
190 int ret_val;
191
192 if ((ret_val = kest_fpga_batch_append(seq, bytes[0])) != NO_ERROR) return ret_val;
193 if ((ret_val = kest_fpga_batch_append(seq, bytes[1])) != NO_ERROR) return ret_val;
194 if ((ret_val = kest_fpga_batch_append(seq, bytes[2])) != NO_ERROR) return ret_val;
195 if ((ret_val = kest_fpga_batch_append(seq, bytes[3])) != NO_ERROR) return ret_val;
196
197 return ret_val;
198}
199
201{
202 if (!seq || !seq2)
203 return ERR_NULL_PTR;
204
205 if (!seq2->buf)
206 return ERR_BAD_ARGS;
207
208 if (!seq->buf)
209 {
210 seq->buf = kest_alloc(seq2->len);
211
212 if (!seq->buf)
213 return ERR_ALLOC_FAIL;
214
215 seq->buf_len = seq2->len;
216 seq->len = 0;
217 }
218 else if (seq->len + seq2->len > seq->buf_len)
219 {
220 int new_len = seq->buf_len;
221 while (new_len < seq->len + seq2->len)
222 new_len *= 2;
223
224 uint8_t *new_ptr = kest_realloc(seq->buf, new_len * sizeof(uint8_t));
225
226 if (!new_ptr) return ERR_ALLOC_FAIL;
227
228 seq->buf_len = new_len;
229 seq->buf = new_ptr;
230 }
231
232 for (int i = 0; i < seq2->len; i++)
233 seq->buf[seq->len + i] = seq2->buf[i];
234
235 seq->len += seq2->len;
236
237 return 0;
238}
239
241{
242 return kest_fpga_txrx(batch.buf, NULL, batch.len);
243}
244
245void kest_fpga_set_input_gain(float gain_db)
246{
247 float v = powf(10, gain_db / 20.0);
248 uint16_t s = float_to_q_nminus1(v, 5);
249
251 kest_fpga_send_byte((s & 0xFF00) >> 8);
252 kest_fpga_send_byte(s & 0x00FF);
253}
254
255void kest_fpga_set_output_gain(float gain_db)
256{
257 float v = powf(10, gain_db / 20.0);
258 uint16_t s = float_to_q_nminus1(v, 5);
259
261 kest_fpga_send_byte((s & 0xFF00) >> 8);
262 kest_fpga_send_byte(s & 0x00FF);
263}
264
265
270
272{
273 switch (command)
274 {
275 case COMMAND_BEGIN_PROGRAM: return "COMMAND_BEGIN_PROGRAM";
276 case COMMAND_WRITE_BLOCK_INSTR: return "COMMAND_WRITE_BLOCK_INSTR";
277 case COMMAND_WRITE_BLOCK_REG_0: return "COMMAND_WRITE_BLOCK_REG_0";
278 case COMMAND_WRITE_BLOCK_REG_1: return "COMMAND_WRITE_BLOCK_REG_1";
279 case COMMAND_ALLOC_DELAY: return "COMMAND_ALLOC_DELAY";
280 case COMMAND_END_PROGRAM: return "COMMAND_END_PROGRAM";
281 case COMMAND_SET_INPUT_GAIN: return "COMMAND_SET_INPUT_GAIN";
282 case COMMAND_SET_OUTPUT_GAIN: return "COMMAND_SET_OUTPUT_GAIN";
283 case COMMAND_UPDATE_BLOCK_REG_0: return "COMMAND_UPDATE_BLOCK_REG_0";
284 case COMMAND_UPDATE_BLOCK_REG_1: return "COMMAND_UPDATE_BLOCK_REG_1";
285 case COMMAND_COMMIT_REG_UPDATES: return "COMMAND_COMMIT_REG_UPDATES";
286 }
287
288 return "UNKNOWN";
289}
void kest_free(void *ptr)
Definition kest_alloc.c:32
void * kest_alloc(size_t size)
Definition kest_alloc.c:11
void * kest_realloc(void *ptr, size_t size)
Definition kest_alloc.c:45
#define ERR_ALLOC_FAIL
#define ERR_BAD_ARGS
#define NO_ERROR
#define ERR_FEATURE_DISABLED
#define ERR_SPI_FAIL
#define ERR_NULL_PTR
kest_fpga_sample_t float_to_q_nminus1(float x, int shift)
#define PIN_NUM_MOSI
void kest_fpga_set_input_gain(float gain_db)
char * kest_fpga_command_to_string(int command)
int kest_fpga_batch_append_16(kest_fpga_transfer_batch *seq, uint16_t x)
int kest_fpga_txrx(uint8_t *tx, uint8_t *rx, size_t len)
#define PIN_NUM_MISO
int kest_fpga_send_byte(uint8_t byte)
void kest_fpga_set_output_gain(float gain_db)
int kest_fpga_batch_append(kest_fpga_transfer_batch *seq, uint8_t x)
#define PIN_NUM_CS
#define PIN_NUM_CLK
spi_device_handle_t spi_handle
int kest_fpga_spi_init()
int kest_fpga_batch_concat(kest_fpga_transfer_batch *seq, kest_fpga_transfer_batch *seq2)
int kest_fpga_batch_append_24(kest_fpga_transfer_batch *seq, uint32_t x)
void kest_free_fpga_transfer_batch(kest_fpga_transfer_batch batch)
uint8_t kest_fpga_read_byte()
void kest_fpga_commit_reg_updates()
int kest_fpga_batch_append_32(kest_fpga_transfer_batch *seq, uint32_t x)
kest_fpga_transfer_batch kest_new_fpga_transfer_batch()
int kest_fpga_transfer_batch_send(kest_fpga_transfer_batch batch)
#define COMMAND_UPDATE_BLOCK_REG_0
#define COMMAND_SET_OUTPUT_GAIN
#define COMMAND_WRITE_BLOCK_REG_0
#define COMMAND_BEGIN_PROGRAM
Definition kest_fpga_io.h:8
#define COMMAND_ALLOC_DELAY
#define KEST_FPGA_N_BLOCKS
#define COMMAND_WRITE_BLOCK_REG_1
#define COMMAND_SET_INPUT_GAIN
#define COMMAND_WRITE_BLOCK_INSTR
Definition kest_fpga_io.h:9
#define COMMAND_COMMIT_REG_UPDATES
#define COMMAND_UPDATE_BLOCK_REG_1
#define COMMAND_END_PROGRAM
#define range_bits(x, n, start)
Definition kest_hfunc.h:22
#define KEST_PRINTF(...)
Definition kest_printf.h:10