-/**
- * File : libsi24.c
- * Author : Robin Krens <robin@robinkrens.nl>
- * Date : 18.01.2023
- * Last Modified Date: 22.01.2023
- * Last Modified By : Robin Krens <robin@robinkrens.nl>
+/* Copyright (C)
+ * 2023 - Robin Krens
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
*/
-
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include "libsi24.h"
#include "libsi24reg.h"
-#define DEBUG 1
+#define DEBUG 0
+#define TIMEOUT 0xFFFF
struct si24_t {
const si24_opts_t *opts;
}
if (params->enable_ack) {
+ if (params->mode == SEND_MODE) {
+ setup_retr_reg = ARD(params->timeout) | ARC(params->retries);
+ ret += _reg_write(si, SI24_REG_SETUP_RETR, &setup_retr_reg, 1);
+ }
+ } else {
+ if (params->mode == SEND_MODE) {
+ feature_reg |= (1 << EN_DYN_ACK);
+ ret += _reg_write(si, SI24_REG_FEATURE, &feature_reg, 1);
+ }
+ }
+
+ if (params->enable_dynpd) {
uint8_t dyn = (1 << DPL_P0);
ret += _reg_write(si, SI24_REG_DYNPD, &dyn, 1);
feature_reg |= (1 << EN_DPL);
ret += _reg_write(si, SI24_REG_FEATURE, &feature_reg, 1);
- setup_retr_reg = ARD(params->timeout) | ARC(params->retries);
- ret += _reg_write(si, SI24_REG_SETUP_RETR, &setup_retr_reg, 1);
- } else {
- feature_reg |= (1 << EN_DYN_ACK);
- ret += _reg_write(si, SI24_REG_FEATURE, &feature_reg, 1);
- }
-
- uint8_t aw;
- if (params->mac_addr & 0xF0000) {
- aw = AW_5;
- ret += _reg_write(si, SI24_REG_SETUP_AW, &aw, 1);
- } else if (params->mac_addr & 0xF000) {
- aw = AW_4;
- ret += _reg_write(si, SI24_REG_SETUP_AW, &aw, 1);
- } else {
- aw = AW_3;
- ret += _reg_write(si, SI24_REG_SETUP_AW, &aw, 1);
+ } else { /* fixed payload size */
+ if (params->mode == RECV_MODE) {
+ ret += _reg_write(si, SI24_REG_RX_PW_P0, (uint8_t *) ¶ms->payload, 1);
+ }
}
- /* quick hack */
- aw += 2;
+ uint8_t aw = AW_5;
+ ret += _reg_write(si, SI24_REG_SETUP_AW, &aw, 1);
if (params->mode == SEND_MODE && params->enable_ack) {
- ret += _reg_write(si, SI24_REG_RX_ADDR_P0, (uint8_t *) ¶ms->mac_addr, aw);
+ ret += _reg_write(si, SI24_REG_RX_ADDR_P0, params->mac_addr, sizeof(params->mac_addr));
}
if (params->mode == RECV_MODE) {
config_reg |= (1 << PRIM_RX);
uint8_t ch = 0x1;
ret += _reg_write(si, SI24_REG_EN_RXADDR, &ch, 1);
- ret += _reg_write(si, SI24_REG_RX_ADDR_P0, (uint8_t *) ¶ms->mac_addr, aw);
- ret += _reg_write(si, SI24_REG_RX_PW_P0, (uint8_t *) ¶ms->payload, 1);
+ ret += _reg_write(si, SI24_REG_RX_ADDR_P0, params->mac_addr, sizeof(params->mac_addr));
} else {
- ret += _reg_write(si, SI24_REG_TX_ADDR, (uint8_t *) ¶ms->mac_addr, aw);
+ ret += _reg_write(si, SI24_REG_TX_ADDR, params->mac_addr, sizeof(params->mac_addr));
}
rf_setup_reg |= (params->speed << RF_DR_HIGH);
ret += _reg_write(si, SI24_REG_RF_CH, &rf_ch_reg, 1);
ret += _reg_write(si, SI24_REG_CONFIG, &config_reg, 1);
+ if (params->mode == RECV_MODE) {
+ /* start accepting data immediately,
+ * for send mode it is onyl activated upon sending */
+ params->ioctl->chip_enable(1);
+ }
+
return ret;
}
size_t si24_send(si24_t* si, const unsigned char * buf, size_t size)
{
si24_event_t ev;
+ size_t bytes_sent = 0;
uint16_t timeout = 0;
int sz;
uint8_t flags;
return -1;
}
- for (size_t idx = 0; idx < size; idx += si->opts->payload) {
- sz = (size - idx) < si->opts->payload ? (size - idx) : si->opts->payload;
+ int payload = si->opts->payload;
+
+ if (si->opts->enable_dynpd)
+ payload = size > 32 ? 32 : size;
+
+ for (size_t idx = 0; idx < size; idx += payload) {
+ sz = (size - idx) < payload ? (size - idx) : payload;
if (si->opts->enable_ack) {
_reg_write(si, SI24_W_TX_PAYLOAD, buf + idx, sz);
si->ctl->chip_enable(1);
- while ((!(flags & (1 << TX_DS)) && !(flags & (1 << MAX_RT))) && timeout < 1000) {
+ while ((!(flags & (1 << TX_DS)) && !(flags & (1 << MAX_RT))) && timeout < TIMEOUT) {
_reg_read(si, SI24_REG_STATUS, &flags, 1);
timeout++;
}
ev.type = EV_ERR_MAX_RETRIES;
si->eh(si, &ev);
si24_reset(si);
- return -1;
+ return bytes_sent;
}
} else {
_reg_write(si, SI24_W_TX_PAYLOAD_NO_ACK, buf + idx, sz);
si->ctl->chip_enable(1);
- while (!(flags & (1 << TX_DS)) && timeout < 1000) {
+ while (!(flags & (1 << TX_DS)) && timeout < TIMEOUT) {
_reg_read(si, SI24_REG_STATUS, &flags, 1);
timeout++;
}
}
- if (timeout >= 1000) {
+ if (timeout >= TIMEOUT) {
ev.type = EV_ERR_TIMEOUT;
si->eh(si, &ev);
si24_reset(si);
- return -1;
+ return bytes_sent;
}
+ flags |= (1 << TX_DS);
+ _reg_write(si, SI24_REG_STATUS, &flags, 1);
+ _reg_read(si, SI24_REG_STATUS, &flags, 1);
+ bytes_sent += sz;
timeout = 0;
}
si->eh(si, &ev);
si->ctl->chip_enable(0);
- return 0;
+ return bytes_sent;
}
size_t si24_recv(si24_t* si, unsigned char * buf, size_t size)
{
- (void) buf;
- (void) size;
+ si24_event_t ev;
+ size_t bytes_read = 0;
+ uint8_t p_size = si->opts->payload;
+ uint8_t tmpbuf[p_size];
+ uint8_t flags;
+ uint8_t fifo_flags;
+
if (si->opts->mode == SEND_MODE)
return -1;
+
+ _reg_read(si, SI24_REG_STATUS, &flags, 1);
+
+ if (!(flags & (1 << RX_DR))) {
+ ev.type = EV_RX_EMPTY;
+ si->eh(si, &ev);
+ return bytes_read;
+ }
+
+ /* do not accept any new incoming data */
+ si->opts->ioctl->chip_enable(0);
+
+ _reg_read(si, SI24_REG_FIFO_SATUS, &fifo_flags, 1);
+ while(!(fifo_flags & (1 << RX_EMPTY)) &&
+ bytes_read < size) {
+
+ if (si->opts->enable_dynpd) {
+ uint8_t d_sz = 0;
+ _reg_read(si, SI24_RX_PL_WID, &d_sz, 1);
+ p_size = d_sz;
+ }
+ int m_size = (size - bytes_read) > p_size ? p_size : (size - bytes_read);
+ _reg_read(si, SI24_R_RX_PAYLOAD, tmpbuf, m_size);
+
+ memcpy(buf + bytes_read, tmpbuf, m_size);
+ bytes_read += m_size;
+
+ _reg_read(si, SI24_REG_FIFO_SATUS, &fifo_flags, 1);
+ }
+
+ /* only clear data ready flag when FIFO is empty */
+ if (fifo_flags & (1 << RX_EMPTY)) {
+ flags |= (1 << RX_DR);
+ _reg_write(si, SI24_REG_STATUS, &flags, 1);
+ }
- uint8_t flags;
- _reg_read(si, 0x7, &flags, 1);
+ ev.type = EV_RX_COMPLETE;
+ si->eh(si, &ev);
+
+ si->opts->ioctl->chip_enable(1);
- return 0;
+ return bytes_read;
}
void si24_reset(si24_t* si)
{
free(si);
}
-
-/* hardware linkage */
-int spi_w_r(unsigned char *data, size_t sz)
-{
- if (sz >= 2)
- data[1] = (1 << TX_DS);
- return sz;
-}
-
-void ce(unsigned val)
-{
-}
-
-void eh(si24_t *si, si24_event_t * e)
-{
- switch(e->type) {
- case EV_TX_COMPLETE:
- printf("SENT SUCCESFUL\n");
- break;
- case EV_ERR_TIMEOUT:
- printf("TIMEOUT\n");
- break;
- default:
- printf("EVENT: %x\n", e->type);
- break;
- }
-}
-
-int main(void)
-{
- const unsigned char buf[] = "THIS IS A WIRELESS TEST MESSAGE!";
-
- si24_ioctl_t ctl = {
- .write_and_read = spi_w_r,
- .chip_enable = ce,
- };
-
- const si24_opts_t opts = {
- .mode = SEND_MODE,
- .enable_ack = 1,
- .non_blocking = 0,
- .enable_crc = 1,
- .enable_dynpd = 1,
- .crc = TWO_BYTE,
- .ioctl = &ctl,
- .speed = MBPS2,
- .txpwr = PLUS4DB,
- .payload = 5,
- .timeout = 1,
- .retries = 5,
- .mac_addr = 0xAAAAAAAAAA
- };
-
- struct si24_t * si = si24_init(&opts, eh);
- si24_send(si, buf, sizeof(buf));
-
-}