3 * Author : Robin Krens <robin@robinkrens.nl>
5 * Last Modified Date: 22.01.2023
6 * Last Modified By : Robin Krens <robin@robinkrens.nl>
16 #include "libsi24reg.h"
19 #define TIMEOUT 0xFFFF
22 const si24_opts_t *opts;
23 const si24_ioctl_t *ctl;
24 si24_event_handler_t eh;
27 static uint8_t _reg_read(si24_t *si, uint8_t reg,
28 uint8_t *data, int sz)
33 buf[0] = reg | SI24_R_REGISTER;
36 if (si->ctl->write_and_read(buf, sz+1) == -1) {
43 memcpy(data, (buf+1), sz);
48 static uint8_t _reg_write(si24_t *si, uint8_t reg,
49 const uint8_t *data, int sz)
53 buf[0] = reg | SI24_W_REGISTER;
54 memcpy((buf+1), data, sz);
57 printf("REG 0x%x:\t", reg);
58 for (int i = 1; i <= sz; ++i) {
59 fprintf(stdout, "0x%x(%c)", buf[i], buf[i]);
61 fprintf(stdout, "\n");
64 if (si->ctl->write_and_read(buf, sz+1) == -1) {
74 static int _config(si24_t * si)
77 uint8_t config_reg = (1 << PWR_UP);
78 uint8_t feature_reg = 0x0; /* default value */
79 uint8_t rf_setup_reg = 0xE; /* default value */
80 uint8_t setup_retr_reg = 0x3; /* default value */
81 const uint8_t rf_ch_reg = 0x40; /* default value */
82 const si24_opts_t * params = si->opts;
84 if (params->enable_crc) {
85 config_reg |= (1 << EN_CRC);
86 config_reg |= (si->opts->crc << CRCO);
89 if (params->enable_ack) {
90 uint8_t dyn = (1 << DPL_P0);
91 ret += _reg_write(si, SI24_REG_DYNPD, &dyn, 1);
92 feature_reg |= (1 << EN_DPL);
93 ret += _reg_write(si, SI24_REG_FEATURE, &feature_reg, 1);
94 if (params->mode == SEND_MODE) {
95 setup_retr_reg = ARD(params->timeout) | ARC(params->retries);
96 ret += _reg_write(si, SI24_REG_SETUP_RETR, &setup_retr_reg, 1);
99 if (params->mode == SEND_MODE) {
100 feature_reg |= (1 << EN_DYN_ACK);
101 ret += _reg_write(si, SI24_REG_FEATURE, &feature_reg, 1);
106 ret += _reg_write(si, SI24_REG_SETUP_AW, &aw, 1);
108 if (params->mode == SEND_MODE && params->enable_ack) {
109 ret += _reg_write(si, SI24_REG_RX_ADDR_P0, params->mac_addr, sizeof(params->mac_addr));
112 if (params->mode == RECV_MODE) {
113 config_reg |= (1 << PRIM_RX);
115 ret += _reg_write(si, SI24_REG_EN_RXADDR, &ch, 1);
116 ret += _reg_write(si, SI24_REG_RX_ADDR_P0, params->mac_addr, sizeof(params->mac_addr));
117 ret += _reg_write(si, SI24_REG_RX_PW_P0, (uint8_t *) ¶ms->payload, 1);
119 ret += _reg_write(si, SI24_REG_TX_ADDR, params->mac_addr, sizeof(params->mac_addr));
122 rf_setup_reg |= (params->speed << RF_DR_HIGH);
123 rf_setup_reg |= (params->txpwr << RF_PWR);
124 ret += _reg_write(si, SI24_REG_RF_SETUP, &rf_setup_reg, 1);
127 ret += _reg_write(si, SI24_REG_RF_CH, &rf_ch_reg, 1);
128 ret += _reg_write(si, SI24_REG_CONFIG, &config_reg, 1);
130 if (params->mode == RECV_MODE) {
131 /* start accepting data immediately,
132 * for send mode it is onyl activated upon sending */
133 params->ioctl->chip_enable(1);
139 si24_t* si24_init(const si24_opts_t *opts, si24_event_handler_t eh)
141 struct si24_t *si = (si24_t*) calloc(1, sizeof(si24_t));
146 si->ctl = opts->ioctl;
149 int ret = _config(si);
158 size_t si24_send(si24_t* si, const unsigned char * buf, size_t size)
161 size_t bytes_sent = 0;
162 uint16_t timeout = 0;
166 if (si->opts->mode == RECV_MODE)
169 _reg_read(si, SI24_REG_STATUS, (uint8_t *) &flags, 1);
171 if (flags & (1 << TX_FULL)) {
172 ev.type = EV_TX_FULL;
177 for (size_t idx = 0; idx < size; idx += si->opts->payload) {
178 sz = (size - idx) < si->opts->payload ? (size - idx) : si->opts->payload;
179 if (si->opts->enable_ack) {
180 _reg_write(si, SI24_W_TX_PAYLOAD, buf + idx, sz);
181 si->ctl->chip_enable(1);
182 while ((!(flags & (1 << TX_DS)) && !(flags & (1 << MAX_RT))) && timeout < TIMEOUT) {
183 _reg_read(si, SI24_REG_STATUS, &flags, 1);
186 if (flags & (1 << MAX_RT)) {
187 ev.type = EV_ERR_MAX_RETRIES;
194 _reg_write(si, SI24_W_TX_PAYLOAD_NO_ACK, buf + idx, sz);
195 si->ctl->chip_enable(1);
196 while (!(flags & (1 << TX_DS)) && timeout < TIMEOUT) {
197 _reg_read(si, SI24_REG_STATUS, &flags, 1);
202 if (timeout >= TIMEOUT) {
203 ev.type = EV_ERR_TIMEOUT;
209 flags |= (1 << TX_DS);
210 _reg_write(si, SI24_REG_STATUS, &flags, 1);
211 _reg_read(si, SI24_REG_STATUS, &flags, 1);
216 ev.type = EV_TX_COMPLETE;
218 si->ctl->chip_enable(0);
223 size_t si24_recv(si24_t* si, unsigned char * buf, size_t size)
226 size_t bytes_read = 0;
227 uint8_t p_size = si->opts->payload;
228 uint8_t tmpbuf[p_size];
232 if (si->opts->mode == SEND_MODE)
235 _reg_read(si, SI24_REG_STATUS, &flags, 1);
237 if (!(flags & (1 << RX_DR))) {
238 ev.type = EV_RX_EMPTY;
243 /* do not accept any new incoming data */
244 si->opts->ioctl->chip_enable(0);
246 _reg_read(si, SI24_REG_FIFO_SATUS, &fifo_flags, 1);
247 while(!(fifo_flags & (1 << RX_EMPTY)) &&
250 int m_size = (size - bytes_read) > p_size ? p_size : (size - bytes_read);
251 _reg_read(si, SI24_R_RX_PAYLOAD, tmpbuf, m_size);
253 memcpy(buf + bytes_read, tmpbuf, m_size);
254 bytes_read += m_size;
256 _reg_read(si, SI24_REG_FIFO_SATUS, &fifo_flags, 1);
259 /* only clear data ready flag when FIFO is empty */
260 if (fifo_flags & (1 << RX_EMPTY)) {
261 flags |= (1 << RX_DR);
262 _reg_write(si, SI24_REG_STATUS, &flags, 1);
265 ev.type = EV_RX_COMPLETE;
268 si->opts->ioctl->chip_enable(1);
273 void si24_reset(si24_t* si)
275 if (si->opts->mode == RECV_MODE) {
276 _reg_write(si, SI24_FLUSH_RX, 0, 0);
278 else if (si->opts->mode == SEND_MODE) {
279 _reg_write(si, SI24_FLUSH_TX, 0, 0);
282 uint8_t status_reg = {0};
283 status_reg |= (1 << RX_DR);
284 status_reg |= (1 << TX_DS);
285 status_reg |= (1 << MAX_RT);
287 _reg_write(si, SI24_REG_STATUS, (uint8_t *) &status_reg, 1);
289 si->ctl->chip_enable(0);
292 void si24_free(si24_t * si)