/mirf_usb/mirf.c
C | 234 lines | 147 code | 35 blank | 52 comment | 23 complexity | 168026f757bf4ab39ca4cd95151842b9 MD5 | raw file
- /*
- Copyright (c) 2013 Mehdi MAAREF <mehdi.maaref@hotmail.fr>
-
- Permission is hereby granted, free of charge, to any person
- obtaining a copy of this software and associated documentation
- files (the "Software"), to deal in the Software without
- restriction, including without limitation the rights to use, copy,
- modify, merge, publish, distribute, sublicense, and/or sell copies
- of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be
- included in all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- DEALINGS IN THE SOFTWARE.
-
- $Id$
- */
- #include <avr/io.h>
- #include <avr/interrupt.h>
- #include <stdlib.h>
- #include <string.h>
-
- #include "mirf.h"
- #include "mirf_config.h"
- #include "nRF24L01.h"
-
-
- #define SPI_FLAG (SPSR & (1<<SPIF))
-
-
- uint8_t *mirf_buffer;
-
- static uint8_t _mirf_buffer[BUFFER_SZ];
- static uint8_t mirf_cmd_len[CMD_BUFFER_SZ]; // len of each command
-
- volatile uint8_t _cmd_len=0; // works also as a busy flag
-
- /**
- * @return the length of the spi buffer when finished
- */
- uint8_t _spi_transfert(void) {
- static uint8_t i=0;
- uint8_t r=0;
-
- if ((MIRF_CSN_ISHI) && i == 0) {
- // init transaction
- MIRF_CSN_LO;
- do {SPDR = mirf_buffer[i];} while (SPSR & 1<<WCOL);
- } else if (SPI_FLAG) {
- // save read byte
- mirf_buffer[i] = SPDR;
- i++;
- if(i < _cmd_len) {
- // send next byte
- do {SPDR = mirf_buffer[i];} while (SPSR & 1<<WCOL);
- r=0;
- } else {
- // last byte is sent
- r = _cmd_len;
- i = 0;
- MIRF_CSN_HI;
- }
- }
-
- return r;
- }
-
- uint8_t mirfPoll(uint8_t *dataBuffer) {
- uint8_t r = 0;
- static uint8_t cnt=0;
-
- if(_cmd_len > 0) {
- r = _spi_transfert(); // if len == 0 CSN is HI
- if ( r > 0) {
- // cmd transfert has just finished during mirf_spi_transfert()
- memcpy(dataBuffer, mirf_buffer, r);
- // is the last command ?
- _cmd_len = (cnt < CMD_BUFFER_SZ-1) ? mirf_cmd_len[cnt+1] : 0;
-
- switch(_cmd_len) {
- case 0x00:
- // transaction is finished
- cnt = 0;
- mirf_buffer = _mirf_buffer; // reset mirf_buffer
- break;
- case 0xff:
- // close command transaction
- MIRF_CE_HI;
- _cmd_len = 0;
- cnt = 0;
- mirf_buffer = _mirf_buffer;
- break;
- case 0xfe:
- MIRF_CE_HI;
- // loop while tx data is not finished
- if(mirf_buffer[0] & (1 << TX_DS | 1 << MAX_RT)) {
- cnt = 0;
- _cmd_len = 0;
- mirf_buffer = _mirf_buffer; // reset mirf_buffer
- // mirf_config();
- } else {
- mirf_buffer[0] = NOP;
- _cmd_len = 1;
- }
- break;
- case 0xf0:
- // hide command data
- r=0;
- default:
- mirf_buffer = &mirf_buffer[mirf_cmd_len[cnt]];
- cnt++;
- break;
- }
-
- return r;
- } else {
- // spare time during the spi transfert, can work with status byte
- }
-
- } else {
- // _cmd_len = 0 so spi is not busy and CSN is HI
- r=0;
-
- }
-
- return r;
- }
-
- // request multiple consecutive commands
- uint8_t mirf_spi_mul_cmd(const uint8_t *buffer, const uint8_t* len) {
- uint8_t i=0, r=0;
-
- if(_cmd_len == 0) {
- for(i=0; (i<CMD_BUFFER_SZ) ; i++) {
- // cp table of lengths
- mirf_cmd_len[i] = len[i];
- if(len[i]<BUFFER_SZ)
- r += len[i];
- }
- if(r>BUFFER_SZ) {
- r=0;
- } else {
- mirf_buffer = _mirf_buffer; // reset mirf_buffer
- memcpy(mirf_buffer, buffer, r); // copy data to internal buffer
- _cmd_len = len[0]; // trigger the spi transfert
- }
- }
- return r;
- }
-
- uint8_t mirf_spi_low_cmd(const uint8_t *buffer, const uint8_t* len) {
-
- uint8_t r = 0;
-
- r = mirf_spi_mul_cmd(buffer, len);
-
- if(r) {
- MIRF_CE_LO;
- }
-
- return r;
- }
-
- inline void spi_init(void)
- // Initialize pins for spi communication
- {
- DDR_SPI &= ~((1<<DD_MOSI)|(1<<DD_MISO)|(1<<DD_SS)|(1<<DD_SCK));
- // Define the following pins as output
- DDR_SPI |= ((1<<DD_MOSI)|(1<<DD_SS)|(1<<DD_SCK));
-
- SPCR = ((1<<SPE)| // SPI Enable
- (0<<SPIE)| // SPI Interupt Enable
- (0<<DORD)| // Data Order (0:MSB first / 1:LSB first)
- (1<<MSTR)| // Master/Slave select
- (0<<SPR1)|(0<<SPR0)| // SPI Clock Rate
- (0<<CPOL)| // Clock Polarity (0:SCK low / 1:SCK hi when idle)
- (0<<CPHA)); // Clock Phase (0:leading / 1:trailing edge sampling)
-
- SPSR = (1<<SPI2X); // Double Clock Rate
-
- }
-
- void mirf_init(void) {
- uint8_t i=0;
- // Define CSN and CE as Output and set them to default
- DDR_CE |= (1<<CE);
- DDR_CSN |= (1<<CSN);
- MIRF_CE_LO;
- MIRF_CSN_HI;
-
- mirf_buffer = _mirf_buffer;
- _cmd_len = 0;
-
- for(i=0;i<CMD_BUFFER_SZ;i++)
- mirf_cmd_len[i] = 0;
- // memset(mirf_cmd_len,0,8);
-
- spi_init();
- }
-
- uint8_t mirf_config(void) {
-
- uint8_t cfg_len_buff[] = { 2, 2, 6, 2, 2, 2, 0xff, 0};
- uint8_t cfg_payload[] =
- { // Set RF channel
- W_REGISTER | (REGISTER_MASK & RF_CH),
- MIRF_CH,
- // RX_POWERUP
- W_REGISTER | (REGISTER_MASK & CONFIG),
- MIRF_CONFIG | ((1<<PWR_UP) | (1<<PRIM_RX)),
- // Set rx adress
- W_REGISTER | (REGISTER_MASK & RX_ADDR_P0),
- 0xb0, 0xb1, 0xb2, 0xb3, 0xb4,
- // Set length of incoming payload
- W_REGISTER | (REGISTER_MASK & RX_PW_P0),
- MIRF_PAYLOAD_SZ,
- // reset TX_DS and MAX_RT
- W_REGISTER | (REGISTER_MASK & STATUS),
- 0x30,
- // read config
- R_REGISTER | (REGISTER_MASK & CONFIG),
- 0x00
- };
-
- return mirf_spi_low_cmd(cfg_payload, cfg_len_buff);
- }