3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU General Public License
5 * as published by the Free Software Foundation; either version 2
6 * of the License, or (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 #include "libsi24reg.h"
28 #define TIMEOUT 0xFFFF
31 const si24_opts_t *opts;
32 const si24_ioctl_t *ctl;
33 si24_event_handler_t eh;
36 static uint8_t _reg_read(si24_t *si, uint8_t reg,
37 uint8_t *data, int sz)
42 buf[0] = reg | SI24_R_REGISTER;
45 if (si->ctl->write_and_read(buf, sz+1) == -1) {
52 memcpy(data, (buf+1), sz);
57 static uint8_t _reg_write(si24_t *si, uint8_t reg,
58 const uint8_t *data, int sz)
62 buf[0] = reg | SI24_W_REGISTER;
63 memcpy((buf+1), data, sz);
66 printf("REG 0x%x:\t", reg);
67 for (int i = 1; i <= sz; ++i) {
68 fprintf(stdout, "0x%x(%c)", buf[i], buf[i]);
70 fprintf(stdout, "\n");
73 if (si->ctl->write_and_read(buf, sz+1) == -1) {
83 static int _config(si24_t * si)
86 uint8_t config_reg = (1 << PWR_UP);
87 uint8_t feature_reg = 0x0; /* default value */
88 uint8_t rf_setup_reg = 0xE; /* default value */
89 uint8_t setup_retr_reg = 0x3; /* default value */
90 const uint8_t rf_ch_reg = 0x40; /* default value */
91 const si24_opts_t * params = si->opts;
93 if (params->enable_crc) {
94 config_reg |= (1 << EN_CRC);
95 config_reg |= (si->opts->crc << CRCO);
98 if (params->enable_ack) {
99 if (params->mode == SEND_MODE) {
100 setup_retr_reg = ARD(params->timeout) | ARC(params->retries);
101 ret += _reg_write(si, SI24_REG_SETUP_RETR, &setup_retr_reg, 1);
104 if (params->mode == SEND_MODE) {
105 feature_reg |= (1 << EN_DYN_ACK);
106 ret += _reg_write(si, SI24_REG_FEATURE, &feature_reg, 1);
110 if (params->enable_dynpd) {
111 uint8_t dyn = (1 << DPL_P0);
112 ret += _reg_write(si, SI24_REG_DYNPD, &dyn, 1);
113 feature_reg |= (1 << EN_DPL);
114 ret += _reg_write(si, SI24_REG_FEATURE, &feature_reg, 1);
115 } else { /* fixed payload size */
116 if (params->mode == RECV_MODE) {
117 ret += _reg_write(si, SI24_REG_RX_PW_P0, (uint8_t *) ¶ms->payload, 1);
122 ret += _reg_write(si, SI24_REG_SETUP_AW, &aw, 1);
124 if (params->mode == SEND_MODE && params->enable_ack) {
125 ret += _reg_write(si, SI24_REG_RX_ADDR_P0, params->mac_addr, sizeof(params->mac_addr));
128 if (params->mode == RECV_MODE) {
129 config_reg |= (1 << PRIM_RX);
131 ret += _reg_write(si, SI24_REG_EN_RXADDR, &ch, 1);
132 ret += _reg_write(si, SI24_REG_RX_ADDR_P0, params->mac_addr, sizeof(params->mac_addr));
134 ret += _reg_write(si, SI24_REG_TX_ADDR, params->mac_addr, sizeof(params->mac_addr));
137 rf_setup_reg |= (params->speed << RF_DR_HIGH);
138 rf_setup_reg |= (params->txpwr << RF_PWR);
139 ret += _reg_write(si, SI24_REG_RF_SETUP, &rf_setup_reg, 1);
142 ret += _reg_write(si, SI24_REG_RF_CH, &rf_ch_reg, 1);
143 ret += _reg_write(si, SI24_REG_CONFIG, &config_reg, 1);
145 if (params->mode == RECV_MODE) {
146 /* start accepting data immediately,
147 * for send mode it is onyl activated upon sending */
148 params->ioctl->chip_enable(1);
154 si24_t* si24_init(const si24_opts_t *opts, si24_event_handler_t eh)
156 struct si24_t *si = (si24_t*) calloc(1, sizeof(si24_t));
161 si->ctl = opts->ioctl;
164 int ret = _config(si);
173 size_t si24_send(si24_t* si, const unsigned char * buf, size_t size)
176 size_t bytes_sent = 0;
177 uint16_t timeout = 0;
181 if (si->opts->mode == RECV_MODE)
184 _reg_read(si, SI24_REG_STATUS, (uint8_t *) &flags, 1);
186 if (flags & (1 << TX_FULL)) {
187 ev.type = EV_TX_FULL;
192 int payload = si->opts->payload;
194 if (si->opts->enable_dynpd)
195 payload = size > 32 ? 32 : size;
197 for (size_t idx = 0; idx < size; idx += payload) {
198 sz = (size - idx) < payload ? (size - idx) : payload;
199 if (si->opts->enable_ack) {
200 _reg_write(si, SI24_W_TX_PAYLOAD, buf + idx, sz);
201 si->ctl->chip_enable(1);
202 while ((!(flags & (1 << TX_DS)) && !(flags & (1 << MAX_RT))) && timeout < TIMEOUT) {
203 _reg_read(si, SI24_REG_STATUS, &flags, 1);
206 if (flags & (1 << MAX_RT)) {
207 ev.type = EV_ERR_MAX_RETRIES;
214 _reg_write(si, SI24_W_TX_PAYLOAD_NO_ACK, buf + idx, sz);
215 si->ctl->chip_enable(1);
216 while (!(flags & (1 << TX_DS)) && timeout < TIMEOUT) {
217 _reg_read(si, SI24_REG_STATUS, &flags, 1);
222 if (timeout >= TIMEOUT) {
223 ev.type = EV_ERR_TIMEOUT;
229 flags |= (1 << TX_DS);
230 _reg_write(si, SI24_REG_STATUS, &flags, 1);
231 _reg_read(si, SI24_REG_STATUS, &flags, 1);
236 ev.type = EV_TX_COMPLETE;
238 si->ctl->chip_enable(0);
243 size_t si24_recv(si24_t* si, unsigned char * buf, size_t size)
246 size_t bytes_read = 0;
247 uint8_t p_size = si->opts->payload;
248 uint8_t tmpbuf[p_size];
252 if (si->opts->mode == SEND_MODE)
255 _reg_read(si, SI24_REG_STATUS, &flags, 1);
257 if (!(flags & (1 << RX_DR))) {
258 ev.type = EV_RX_EMPTY;
263 /* do not accept any new incoming data */
264 si->opts->ioctl->chip_enable(0);
266 _reg_read(si, SI24_REG_FIFO_SATUS, &fifo_flags, 1);
267 while(!(fifo_flags & (1 << RX_EMPTY)) &&
270 if (si->opts->enable_dynpd) {
272 _reg_read(si, SI24_RX_PL_WID, &d_sz, 1);
275 int m_size = (size - bytes_read) > p_size ? p_size : (size - bytes_read);
276 _reg_read(si, SI24_R_RX_PAYLOAD, tmpbuf, m_size);
278 memcpy(buf + bytes_read, tmpbuf, m_size);
279 bytes_read += m_size;
281 _reg_read(si, SI24_REG_FIFO_SATUS, &fifo_flags, 1);
284 /* only clear data ready flag when FIFO is empty */
285 if (fifo_flags & (1 << RX_EMPTY)) {
286 flags |= (1 << RX_DR);
287 _reg_write(si, SI24_REG_STATUS, &flags, 1);
290 ev.type = EV_RX_COMPLETE;
293 si->opts->ioctl->chip_enable(1);
298 void si24_reset(si24_t* si)
300 if (si->opts->mode == RECV_MODE) {
301 _reg_write(si, SI24_FLUSH_RX, 0, 0);
303 else if (si->opts->mode == SEND_MODE) {
304 _reg_write(si, SI24_FLUSH_TX, 0, 0);
307 uint8_t status_reg = {0};
308 status_reg |= (1 << RX_DR);
309 status_reg |= (1 << TX_DS);
310 status_reg |= (1 << MAX_RT);
312 _reg_write(si, SI24_REG_STATUS, (uint8_t *) &status_reg, 1);
314 si->ctl->chip_enable(0);
317 void si24_free(si24_t * si)