[superbitrf] Initial commit for superbitrf 2.4GHz radio control

This commit is contained in:
fvantienen
2013-07-02 16:40:40 +02:00
parent d744f8ca2c
commit 03c3b8f43a
11 changed files with 892 additions and 5 deletions
@@ -12,9 +12,7 @@
<firmware name="rotorcraft">
<target name="ap" board="lisa_m_2.0">
<subsystem name="radio_control" type="spektrum">
<define name="RADIO_MODE" value="RADIO_AUX1"/>
<configure name="USE_SECONDARY_SPEKTRUM_RECEIVER" value="1"/>
<subsystem name="radio_control" type="superbitrf">
</subsystem>
<!-- MPU6000 is configured to output data at 2kHz, but polled at 512Hz PERIODIC_FREQUENCY -->
</target>
@@ -0,0 +1,14 @@
#
# Makefile for shared radio_control superbitrf subsystem
#
ap.CFLAGS += -DRADIO_CONTROL -DRADIO_CONTROL_TYPE_SUPERBITRF -DRADIO_CONTROL_TYPE_H=\"subsystems/radio_control/superbitrf.h\"
ap.CFLAGS += -DUSE_SPI1 -DUSE_SPI_SLAVE1
ifneq ($(RADIO_CONTROL_LED),none)
ap.CFLAGS += -DRADIO_CONTROL_LED=$(RADIO_CONTROL_LED)
endif
ap.srcs += peripherals/cyrf6936.c \
$(SRC_SUBSYSTEMS)/radio_control.c \
$(SRC_SUBSYSTEMS)/radio_control/superbitrf.c
+5 -2
View File
@@ -603,8 +603,11 @@
<field name="ping_time" type="float" format="%.2f" unit="ms"/>
</message>
<!-- 72 is free -->
<message name="SUPERBITRF" id="72">
<field name="status" type="uint8" values="UNINIT|INIT_BINDING|INIT_TRANSFER|BINDING|TRANSFER"/>
<field name="cyrf_status" type="uint8" values="UNINIT|IDLE|GET_MFG_ID|MULTIWRITE|CHAN_SOP_DATA_CRC|RX_IRQ_STATUS_PACKET"/>
<field name="mfg_id" type="uint8[]"/>
</message>
<message name="GX3_INFO" id="73">
<field name="GX3_freq" type="float" unit="hz"/>
+1
View File
@@ -26,6 +26,7 @@
<message name="RC" period="0.5"/>
<message name="ROTORCRAFT_RADIO_CONTROL" period="0.5"/>
<message name="ROTORCRAFT_STATUS" period="1"/>
<message name="SUPERBITRF" period="0.5"/>
</mode>
<mode name="raw_sensors">
@@ -134,6 +134,18 @@
#define PERIODIC_SEND_PPM(_trans, _dev) {}
#endif
#ifdef RADIO_CONTROL_TYPE_SUPERBITRF
#include "subsystems/radio_control/superbitrf.h"
#define PERIODIC_SEND_SUPERBITRF(_trans, _dev) { \
DOWNLINK_SEND_SUPERBITRF(_trans, _dev, \
&superbitrf.status, \
&superbitrf.cyrf6936.status, \
6, \
superbitrf.cyrf6936.mfg_id);}
#else
#define PERIODIC_SEND_SUPERBITRF(_trans, _dev) {}
#endif
#ifdef ACTUATORS
#define PERIODIC_SEND_ACTUATORS(_trans, _dev) DOWNLINK_SEND_ACTUATORS(_trans, _dev, ACTUATORS_NB, actuators)
#else
+4
View File
@@ -25,6 +25,9 @@
* Some architecture independent helper functions for GPIOs.
*/
#ifndef MCU_PERIPH_GPIO_H
#define MCU_PERIPH_GPIO_H
#include "std.h"
#include "mcu_periph/gpio_arch.h"
@@ -38,3 +41,4 @@ extern void gpio_setup_output(uint32_t port, uint16_t pin);
*/
extern void gpio_setup_input(uint32_t port, uint16_t pin);
#endif /* MCU_PERIPH_GPIO_H */
+359
View File
@@ -0,0 +1,359 @@
/*
* Copyright (C) 2013 Freek van Tienen <freek.v.tienen@gmail.com>
*
* This file is part of paparazzi.
*
* paparazzi 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, or (at your option)
* any later version.
*
* paparazzi 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 paparazzi; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
* @file peripherals/cyrf6936.c
* Driver for the cyrf6936 2.4GHz radio chip
*/
#include "cyrf6936.h"
#include "mcu_periph/spi.h"
#include "mcu_periph/gpio.h"
#include "mcu_periph/gpio_arch.h"
#include "subsystems/radio_control.h"
#include "mcu_periph/uart.h"
#include "messages.h"
#include "subsystems/datalink/downlink.h"
/* Static functions used in the different statuses */
static bool_t cyrf6936_write_register(struct Cyrf6936 *cyrf, const uint8_t addr, const uint8_t data);
static bool_t cyrf6936_write_block(struct Cyrf6936 *cyrf, const uint8_t addr, const uint8_t data[], const uint8_t length);
static bool_t cyrf6936_read_register(struct Cyrf6936 *cyrf, const uint8_t addr);
static bool_t cyrf6936_read_block(struct Cyrf6936 *cyrf, const uint8_t addr, const uint8_t length);
//FIXME
void Delay(uint32_t x);
void Delay(uint32_t x)
{
(void)x;
__asm ("mov r1, #24;"
"mul r0, r0, r1;"
"b _delaycmp;"
"_delayloop:"
"subs r0, r0, #1;"
"_delaycmp:;"
"cmp r0, #0;"
" bne _delayloop;");
}
/**
* Initializing the cyrf chip
*/
void cyrf6936_init(struct Cyrf6936 *cyrf, struct spi_periph *spi_p, const uint8_t slave_idx, const uint32_t rst_port, const uint16_t rst_pin) {
/* Set spi_peripheral and the status */
cyrf->spi_p = spi_p;
cyrf->status = CYRF6936_UNINIT;
/* Set the spi transaction */
cyrf->spi_t.cpol = SPICpolIdleLow;
cyrf->spi_t.cpha = SPICphaEdge1;
cyrf->spi_t.dss = SPIDss8bit;
cyrf->spi_t.bitorder = SPIMSBFirst;
cyrf->spi_t.cdiv = SPIDiv64;
cyrf->spi_t.input_length = 0;
cyrf->spi_t.output_length = 0;
cyrf->spi_t.input_buf = cyrf->input_buf;
cyrf->spi_t.output_buf = cyrf->output_buf;
cyrf->spi_t.slave_idx = slave_idx;
cyrf->spi_t.select = SPISelectUnselect;
cyrf->spi_t.status = SPITransDone;
/* Reset the CYRF6936 chip */
gpio_setup_output(rst_port, rst_pin);
gpio_output_high(rst_port, rst_pin);
Delay(100);
gpio_output_low(rst_port, rst_pin);
Delay(100);
/* Get the MFG ID */
cyrf->status = CYRF6936_GET_MFG_ID;
cyrf->buffer_idx = 0;
cyrf6936_write_register(cyrf, CYRF_MFG_ID, 0xFF);
}
/**
* The on event call for the CYRF6936 chip
*/
void cyrf6936_event(struct Cyrf6936 *cyrf) {
int i;
// Check if cyrf is initialized
if(cyrf->status == CYRF6936_UNINIT)
return;
// Check if there is still a transaction in progress
if(cyrf->spi_t.status == SPITransPending || cyrf->spi_t.status == SPITransRunning)
return;
/* Check the status of the cyrf */
switch (cyrf->status) {
/* Getting the MFG id */
case CYRF6936_GET_MFG_ID:
// When the last transaction isn't failed send the next
if(cyrf->spi_t.status != SPITransFailed)
cyrf->buffer_idx++;
cyrf->spi_t.status = SPITransDone;
// Switch for the different states
switch (cyrf->buffer_idx) {
case 0:
cyrf6936_write_register(cyrf, CYRF_MFG_ID, 0xFF);
break;
case 1:
cyrf6936_read_block(cyrf, CYRF_MFG_ID, 6);
break;
case 2:
// Copy the MFG id
for(i = 0; i < 6; i++)
cyrf->mfg_id[i] = cyrf->input_buf[i+1];
cyrf6936_write_register(cyrf, CYRF_MFG_ID, 0x00);
break;
default:
cyrf->status = CYRF6936_IDLE;
break;
}
break;
/* Do a multi write */
case CYRF6936_MULTIWRITE:
// When the last transaction isn't failed send the next
if(cyrf->spi_t.status != SPITransFailed)
cyrf->buffer_idx++;
cyrf->spi_t.status = SPITransDone;
// When we are done writing
if(cyrf->buffer_idx == cyrf->buffer_length) {
cyrf->status = CYRF6936_IDLE;
break;
}
// Write the next register from the buffer
cyrf6936_write_register(cyrf,
((uint8_t (*)[2])cyrf->buffer)[cyrf->buffer_idx][0],
((uint8_t (*)[2])cyrf->buffer)[cyrf->buffer_idx][1]);
break;
/* Do a write of channel, sop, data and crc */
case CYRF6936_CHAN_SOP_DATA_CRC:
// When the last transaction isn't failed send the next
if(cyrf->spi_t.status != SPITransFailed)
cyrf->buffer_idx++;
cyrf->spi_t.status = SPITransDone;
// Switch for the different states
switch (cyrf->buffer_idx) {
case 0: // Write the CRC LSB
cyrf6936_write_register(cyrf, CYRF_CRC_SEED_LSB, cyrf->buffer[0]);
break;
case 1: // Write the CRC MSB
cyrf6936_write_register(cyrf, CYRF_CRC_SEED_MSB, cyrf->buffer[1]);
break;
case 2: // Write the SOP code
cyrf6936_write_block(cyrf, CYRF_SOP_CODE, &(cyrf->buffer[2]), 8);
break;
case 3: // Write the DATA code
cyrf6936_write_block(cyrf, CYRF_DATA_CODE, &(cyrf->buffer[10]), 16);
break;
case 4: // Write the Channel
cyrf6936_write_register(cyrf, CYRF_CHANNEL, cyrf->buffer[26]);
break;
default:
cyrf->status = CYRF6936_IDLE;
break;
}
break;
/* Do a read of the receive irq status, receive status and the receive packet */
case CYRF6936_RX_IRQ_STATUS_PACKET:
// When the last transaction isn't failed send the next
if(cyrf->spi_t.status != SPITransFailed)
cyrf->buffer_idx++;
cyrf->spi_t.status = SPITransDone;
// Switch for the different states
switch (cyrf->buffer_idx) {
case 0: // Read the receive IRQ status
cyrf6936_read_register(cyrf, CYRF_RX_IRQ_STATUS);
break;
case 1: // Read the receive status
cyrf->rx_irq_status = cyrf->input_buf[1];
cyrf6936_read_register(cyrf, CYRF_RX_STATUS);
break;
case 2: // Read the receive packet
cyrf->rx_status = cyrf->input_buf[1];
cyrf6936_read_block(cyrf, CYRF_RX_BUFFER, 16);
break;
default:
// Copy the receive packet
for(i = 0; i < 16; i++)
cyrf->rx_packet[i] = cyrf->input_buf[i+1];
cyrf->status = CYRF6936_IDLE;
break;
}
break;
/* This should not happen */
default:
break;
}
}
/**
* Write a byte to a register
*/
static bool_t cyrf6936_write_register(struct Cyrf6936 *cyrf, const uint8_t addr, const uint8_t data) {
return cyrf6936_write_block(cyrf, addr, &data, 1);
}
/**
* Write multiple bytes to a register
*/
static bool_t cyrf6936_write_block(struct Cyrf6936 *cyrf, const uint8_t addr, const uint8_t data[], const uint8_t length) {
uint8_t i;
/* Check if there is already a SPI transaction busy */
if(cyrf->spi_t.status != SPITransDone)
return FALSE;
/* Set the buffer and commit the transaction */
cyrf->spi_t.output_length = length+1;
cyrf->spi_t.input_length = 0;
cyrf->output_buf[0] = addr | CYRF_DIR;
// Copy the data
for(i = 0; i < length; i++)
cyrf->output_buf[i+1] = data[i];
// Submit the transaction
return spi_submit(cyrf->spi_p, &(cyrf->spi_t));
}
/**
* Read a byte from a register
*/
static bool_t cyrf6936_read_register(struct Cyrf6936 *cyrf, const uint8_t addr) {
return cyrf6936_read_block(cyrf, addr, 1);
}
/**
* Read multiple bytes from a register
*/
static bool_t cyrf6936_read_block(struct Cyrf6936 *cyrf, const uint8_t addr, const uint8_t length) {
if(cyrf->spi_t.status != SPITransDone)
return FALSE;
/* Set the buffer and commit the transaction */
cyrf->spi_t.output_length = 1;
cyrf->spi_t.input_length = length + 1;
cyrf->output_buf[0] = addr;
// Submit the transaction
return spi_submit(cyrf->spi_p, &(cyrf->spi_t));
}
/**
* Write to multiple registers one byte
*/
bool_t cyrf6936_multi_write(struct Cyrf6936 *cyrf, const uint8_t data[][2], const uint8_t length) {
uint8_t i;
/* Check if the cyrf6936 isn't busy */
if(cyrf->status != CYRF6936_IDLE)
return FALSE;
// Set the status
cyrf->status = CYRF6936_MULTIWRITE;
/* Set the multi write */
cyrf->buffer_length = length;
cyrf->buffer_idx = 0;
// Copy the buffer
for(i = 0; i< length; i++) {
cyrf->buffer[i*2] = data[i][0];
cyrf->buffer[i*2+1] = data[i][1];
}
/* Write the first regiter */
if(length > 0)
cyrf6936_write_register(cyrf, data[0][0], data[0][1]);
return TRUE;
}
/**
* Set the channel, SOP code, DATA code and the CRC seed
*/
bool_t cyrf6936_write_chan_sop_data_crc(struct Cyrf6936 *cyrf, const uint8_t chan, const uint8_t sop_code[], const uint8_t data_code[], const uint16_t crc_seed) {
uint8_t i;
/* Check if the cyrf6936 isn't busy */
if(cyrf->status != CYRF6936_IDLE)
return FALSE;
// Set the status
cyrf->status = CYRF6936_CHAN_SOP_DATA_CRC;
// Copy the CRC
cyrf->buffer[0] = crc_seed & 0xFF;
cyrf->buffer[1] = (crc_seed >> 8) & 0xFF;
// Copy the SOP code
for(i = 0; i < 8; i++)
cyrf->buffer[i+2] = sop_code[i];
// Copy the DATA code
for(i = 0; i < 16; i++)
cyrf->buffer[i+10] = data_code[i];
// Copy the channel
cyrf->buffer[26] = chan;
/* Try to write the CRC LSB */
cyrf->buffer_idx = 0;
cyrf6936_write_register(cyrf, CYRF_CRC_SEED_LSB, cyrf->buffer[0]);
return TRUE;
}
/**
* Read the RX IRQ status register, the rx status register and the rx packet
*/
bool_t cyrf6936_read_rx_irq_status_packet(struct Cyrf6936 *cyrf) {
/* Check if the cyrf6936 isn't busy */
if(cyrf->status != CYRF6936_IDLE)
return FALSE;
// Set the status
cyrf->status = CYRF6936_RX_IRQ_STATUS_PACKET;
/* Try to read the RX status */
cyrf->buffer_idx = 0;
cyrf6936_read_register(cyrf, CYRF_RX_IRQ_STATUS);
return TRUE;
}
+70
View File
@@ -0,0 +1,70 @@
/*
* Copyright (C) 2013 Freek van Tienen <freek.v.tienen@gmail.com>
*
* This file is part of paparazzi.
*
* paparazzi 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, or (at your option)
* any later version.
*
* paparazzi 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 paparazzi; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
* @file peripherals/yrf6936c.h
* Driver for the cyrf6936 2.4GHz radio chip
*/
#ifndef CYRF6936_H
#define CYRF6936_H
#include "cyrf6936_regs.h"
#include "mcu_periph/spi.h"
#define CYRF6936_MAX_BUFFER 80 /**< The max buffer size in the cyrf6936 structure */
/* The different statuses the cyrf6936 chip can be in */
enum Cyrf6936Status {
CYRF6936_UNINIT, /**< The chip isn't initialized */
CYRF6936_IDLE, /**< The chip is idle and can be used */
CYRF6936_GET_MFG_ID, /**< The chip is busy with getting the manufacturer ID */
CYRF6936_MULTIWRITE, /**< The chip is writing multiple registers */
CYRF6936_CHAN_SOP_DATA_CRC, /**< The chip is setting the channel, SOP code, DATA code and the CRC seed */
CYRF6936_RX_IRQ_STATUS_PACKET /**< The chip is getting the receive irq status, receive status and the receive packet */
};
/* The structure for the cyrf6936 chip that handles all the buffers and requests */
struct Cyrf6936 {
struct spi_periph *spi_p; /**< The SPI peripheral for the connection */
struct spi_transaction spi_t; /**< The SPI transaction used for the writing and reading of registers */
volatile enum Cyrf6936Status status; /**< The status of the CYRF6936 chip */
uint8_t input_buf[17]; /**< The input buffer for the SPI transaction */
uint8_t output_buf[17]; /**< The output buffer for the SPI transaction */
uint8_t buffer[CYRF6936_MAX_BUFFER]; /**< The buffer used to write/read multiple registers */
uint8_t buffer_length; /**< The length of the buffer used for MULTIWRITE */
uint8_t buffer_idx; /**< The index of the buffer used for MULTIWRITE and used as sub-status for other statuses */
uint8_t mfg_id[6]; /**< The manufacturer id of the CYRF6936 chip */
uint8_t rx_irq_status; /**< The last receive interrupt status */
uint8_t rx_status; /**< The last receive status */
uint8_t rx_packet[16]; /**< The last received packet */
};
extern void cyrf6936_init(struct Cyrf6936 *cyrf, struct spi_periph *spi_p, const uint8_t slave_idx, const uint32_t rst_port, const uint16_t rst_pin);
void cyrf6936_event(struct Cyrf6936 *cyrf);
bool_t cyrf6936_multi_write(struct Cyrf6936 *cyrf, const uint8_t data[][2], const uint8_t length);
bool_t cyrf6936_write_chan_sop_data_crc(struct Cyrf6936 *cyrf, const uint8_t chan, const uint8_t sop_code[], const uint8_t data_code[], const uint16_t crc_seed);
bool_t cyrf6936_read_rx_irq_status_packet(struct Cyrf6936 *cyrf);
#endif /* CYRF6936_H */
+211
View File
@@ -0,0 +1,211 @@
/*
* Copyright (C) 2013 Freek van Tienen <freek.v.tienen@gmail.com>
*
* This file is part of paparazzi.
*
* paparazzi 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, or (at your option)
* any later version.
*
* paparazzi 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 paparazzi; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
* @file peripherals/cyrf6936_regs.h
* Register defines for the CYRF6936 2.4GHz radio chip
*/
#ifndef CYRF6936_REGS_H
#define CYRF6936_REGS_H
/* The SPI interface defines */
enum {
CYRF_CHANNEL = 0x00,
CYRF_TX_LENGTH = 0x01,
CYRF_TX_CTRL = 0x02,
CYRF_TX_CFG = 0x03,
CYRF_TX_IRQ_STATUS = 0x04,
CYRF_RX_CTRL = 0x05,
CYRF_RX_CFG = 0x06,
CYRF_RX_IRQ_STATUS = 0x07,
CYRF_RX_STATUS = 0x08,
CYRF_RX_COUNT = 0x09,
CYRF_RX_LENGTH = 0x0A,
CYRF_PWR_CTRL = 0x0B,
CYRF_XTAL_CTRL = 0x0C,
CYRF_IO_CFG = 0x0D,
CYRF_GPIO_CTRL = 0x0E,
CYRF_XACT_CFG = 0x0F,
CYRF_FRAMING_CFG = 0x10,
CYRF_DATA32_THOLD = 0x11,
CYRF_DATA64_THOLD = 0x12,
CYRF_RSSI = 0x13,
CYRF_EOP_CTRL = 0x14,
CYRF_CRC_SEED_LSB = 0x15,
CYRF_CRC_SEED_MSB = 0x16,
CYRF_TX_CRC_LSB = 0x17,
CYRF_TX_CRC_MSB = 0x18,
CYRF_RX_CRC_LSB = 0x19,
CYRF_RX_CRC_MSB = 0x1A,
CYRF_TX_OFFSET_LSB = 0x1B,
CYRF_TX_OFFSET_MSB = 0x1C,
CYRF_MODE_OVERRIDE = 0x1D,
CYRF_RX_OVERRIDE = 0x1E,
CYRF_TX_OVERRIDE = 0x1F,
CYRF_TX_BUFFER = 0x20,
CYRF_RX_BUFFER = 0x21,
CYRF_SOP_CODE = 0x22,
CYRF_DATA_CODE = 0x23,
CYRF_PREAMBLE = 0x24,
CYRF_MFG_ID = 0x25,
CYRF_XTAL_CFG = 0x26,
CYRF_CLK_OFFSET = 0x27,
CYRF_CLK_EN = 0x28,
CYRF_RX_ABORT = 0x29,
CYRF_AUTO_CAL_TIME = 0x32,
CYRF_AUTO_CAL_OFFSET = 0x35,
CYRF_ANALOG_CTRL = 0x39,
};
#define CYRF_DIR (1<<7) /**< Bit for enabling writing */
// CYRF_MODE_OVERRIDE
#define CYRF_RST (1<<0)
// CYRF_CLK_EN
#define CYRF_RXF (1<<1)
// CYRF_XACT_CFG
enum {
CYRF_MODE_SLEEP = (0x0 <<2),
CYRF_MODE_IDLE = (0x1 <<2),
CYRF_MODE_SYNTH_TX = (0x2 <<2),
CYRF_MODE_SYNTH_RX = (0x3 <<2),
CYRF_MODE_RX = (0x4 <<2),
};
#define CYRF_FRC_END (1<<5)
#define CYRF_ACK_EN (1<<7)
// CYRF_IO_CFG
#define CYRF_IRQ_GPIO (1<<0)
#define CYRF_SPI_3PIN (1<<1)
#define CYRF_PACTL_GPIO (1<<2)
#define CYRF_PACTL_OD (1<<3)
#define CYRF_XOUT_OD (1<<4)
#define CYRF_MISO_OD (1<<5)
#define CYRF_IRQ_POL (1<<6)
#define CYRF_IRQ_OD (1<<7)
// CYRF_FRAMING_CFG
#define CYRF_LEN_EN (1<<5)
#define CYRF_SOP_LEN (1<<6)
#define CYRF_SOP_EN (1<<7)
// CYRF_RX_STATUS
enum {
CYRF_RX_DATA_MODE_GFSK = 0x00,
CYRF_RX_DATA_MODE_8DR = 0x01,
CYRF_RX_DATA_MODE_DDR = 0x10,
CYRF_RX_DATA_MODE_NV = 0x11,
};
#define CYRF_RX_CODE (1<<2)
#define CYRF_BAD_CRC (1<<3)
#define CYRF_CRC0 (1<<4)
#define CYRF_EOP_ERR (1<<5)
#define CYRF_PKT_ERR (1<<6)
#define CYRF_RX_ACK (1<<7)
// CYRF_TX_IRQ_STATUS
#define CYRF_TXE_IRQ (1<<0)
#define CYRF_TXC_IRQ (1<<1)
#define CYRF_TXBERR_IRQ (1<<2)
#define CYRF_TXB0_IRQ (1<<3)
#define CYRF_TXB8_IRQ (1<<4)
#define CYRF_TXB15_IRQ (1<<5)
#define CYRF_LV_IRQ (1<<6)
#define CYRF_OS_IRQ (1<<7)
// CYRF_RX_IRQ_STATUS
#define CYRF_RXE_IRQ (1<<0)
#define CYRF_RXC_IRQ (1<<1)
#define CYRF_RXBERR_IRQ (1<<2)
#define CYRF_RXB1_IRQ (1<<3)
#define CYRF_RXB8_IRQ (1<<4)
#define CYRF_RXB16_IRQ (1<<5)
#define CYRF_SOPDET_IRQ (1<<6)
#define CYRF_RXOW_IRQ (1<<7)
// CYRF_TX_CTRL
#define CYRF_TXE_IRQEN (1<<0)
#define CYRF_TXC_IRQEN (1<<1)
#define CYRF_TXBERR_IRQEN (1<<2)
#define CYRF_TXB0_IRQEN (1<<3)
#define CYRF_TXB8_IRQEN (1<<4)
#define CYRF_TXB15_IRQEN (1<<5)
#define CYRF_TX_CLR (1<<6)
#define CYRF_TX_GO (1<<7)
// CYRF_RX_CTRL
#define CYRF_RXE_IRQEN (1<<0)
#define CYRF_RXC_IRQEN (1<<1)
#define CYRF_RXBERR_IRQEN (1<<2)
#define CYRF_RXB1_IRQEN (1<<3)
#define CYRF_RXB8_IRQEN (1<<4)
#define CYRF_RXB16_IRQEN (1<<5)
#define CYRF_RSVD (1<<6)
#define CYRF_RX_GO (1<<7)
// CYRF_RX_OVERRIDE
#define CYRF_ACE (1<<1)
#define CYRF_DIS_RXCRC (1<<2)
#define CYRF_DIS_CRC0 (1<<3)
#define CYRF_FRC_RXDR (1<<4)
#define CYRF_MAN_RXACK (1<<5)
#define CYRF_RXTX_DLY (1<<6)
#define CYRF_ACK_RX (1<<7)
// CYRF_TX_OVERRIDE
#define CYRF_TX_INV (1<<0)
#define CYRF_DIS_TXCRC (1<<2)
#define CYRF_OVRD_ACK (1<<3)
#define CYRF_MAN_TXACK (1<<4)
#define CYRF_FRC_PRE (1<<6)
#define CYRF_ACK_TX (1<<7)
// CYRF_RX_CFG
#define CYRF_VLD_EN (1<<0)
#define CYRF_RXOW_EN (1<<1)
#define CYRF_FAST_TURN_EN (1<<3)
#define CYRF_HILO (1<<4)
#define CYRF_ATT (1<<5)
#define CYRF_LNA (1<<6)
#define CYRF_AGC_EN (1<<7)
// CYRF_TX_CFG
enum {
CYRF_PA_M35 = 0x0,
CYRF_PA_M30 = 0x1,
CYRF_PA_M24 = 0x2,
CYRF_PA_M18 = 0x3,
CYRF_PA_M13 = 0x4,
CYRF_PA_M5 = 0x5,
CYRF_PA_0 = 0x6,
CYRF_PA_4 = 0x7,
};
enum {
CYRF_DATA_MODE_GFSK = (0x0 <<3),
CYRF_DATA_MODE_8DR = (0x1 <<3),
CYRF_DATA_MODE_DDR = (0x2 <<3),
CYRF_DATA_MODE_SDR = (0x3 <<3),
};
#define CYRF_DATA_CODE_LENGTH (1<<5)
#endif // CYRF6936_REGS_H
@@ -0,0 +1,129 @@
/*
* Copyright (C) 2013 Freek van Tienen <freek.v.tienen@gmail.com>
*
* This file is part of paparazzi.
*
* paparazzi 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, or (at your option)
* any later version.
*
* paparazzi 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 paparazzi; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
* @file subsystems/radio_control/superbitrf.c
* DSM2 and DSMX implementation for the cyrf6936 2.4GHz radio chip trough SPI
*/
#include "superbitrf.h"
#include "subsystems/radio_control.h"
#include "mcu_periph/spi.h"
#include <libopencm3/stm32/gpio.h>
/* Default SuperbitRF SPI DEV */
#ifndef SUPERBITRF_SPI_DEV
#define SUPERBITRF_SPI_DEV spi1
#endif
/* Default SuperbitRF RST PORT and PIN */
#ifndef SUPERBITRF_RST_PORT
#define SUPERBITRF_RST_PORT GPIOC
#endif
#ifndef SUPERBITRF_RST_PIN
#define SUPERBITRF_RST_PIN GPIO12
#endif
/* Default SuperbitRF DRDY(IRQ) PORT and PIN */
#ifndef SUPERBITRF_DRDY_PORT
#define SUPERBITRF_DRDY_PORT GPIOB
#endif
#ifndef SUPERBITRF_DRDY_PIN
#define SUPERBITRF_DRDY_PIN GPIO1
#endif
/* The superbitRF structure */
struct SuperbitRF superbitrf;
/* The startup configuration for the cyrf6936 */
static const uint8_t cyrf_stratup_config[][2] = {
{CYRF_MODE_OVERRIDE, CYRF_RST}, // Reset the device
{CYRF_CLK_EN, CYRF_RXF}, // Enable the clock
{CYRF_AUTO_CAL_TIME, 0x3C}, // From manual, needed for initialization
{CYRF_AUTO_CAL_OFFSET, 0x14}, // From manual, needed for initialization
{CYRF_RX_CFG, CYRF_LNA | CYRF_FAST_TURN_EN}, // Enable low noise amplifier and fast turning
{CYRF_TX_OFFSET_LSB, 0x55}, // From manual, typical configuration
{CYRF_TX_OFFSET_MSB, 0x05}, // From manual, typical configuration
{CYRF_XACT_CFG, CYRF_MODE_SYNTH_RX | CYRF_FRC_END}, // Force in Synth RX mode
{CYRF_TX_CFG, CYRF_DATA_CODE_LENGTH | CYRF_DATA_MODE_SDR | CYRF_PA_4}, // Enable 64 chip codes, SDR mode and amplifier +4dBm
{CYRF_DATA64_THOLD, 0x0E}, // From manual, typical configuration
{CYRF_XACT_CFG, CYRF_MODE_SYNTH_RX}, // Set in Synth RX mode (again, really needed?)
};
/* The binding configuration for the cyrf6936 */
static const uint8_t cyrf_bind_config[][2] = {
{CYRF_TX_CFG, CYRF_DATA_CODE_LENGTH | CYRF_DATA_MODE_SDR | CYRF_PA_4}, // Enable 64 chip codes, SDR mode and amplifier +4dBm
{CYRF_FRAMING_CFG, CYRF_SOP_LEN | 0xE}, // Set SOP CODE to 64 chips and SOP Correlator Threshold to 0xE
{CYRF_RX_OVERRIDE, CYRF_FRC_RXDR | CYRF_DIS_RXCRC}, // Force receive data rate and disable receive CRC checker
{CYRF_EOP_CTRL, 0x02}, // Only enable EOP symbol count of 2
{CYRF_TX_OVERRIDE, CYRF_DIS_TXCRC}, // Disable transmit CRC generate
};
/**
* Initialize the superbitrf
*/
void radio_control_impl_init(void) {
// Set the status to uninitialized
superbitrf.status = SUPERBITRF_UNINIT;
// Initialize the binding pin
gpio_setup_input(SPEKTRUM_BIND_PIN_PORT, SPEKTRUM_BIND_PIN);
// Initialize the cyrf6936 chip
cyrf6936_init(&superbitrf.cyrf6936, &(SUPERBITRF_SPI_DEV), 1, SUPERBITRF_RST_PORT, SUPERBITRF_RST_PIN);
}
/**
* The superbitrf on event call
*/
void superbitrf_event(void) {
// Check the status
switch(superbitrf.status) {
/* When the superbitrf isn't initialized */
case SUPERBITRF_UNINIT:
// Try to write the startup config
if(cyrf6936_multi_write(&superbitrf.cyrf6936, cyrf_stratup_config, 11)) {
// Check if need to go to bind or transfer
if(gpio_get(SPEKTRUM_BIND_PIN_PORT, SPEKTRUM_BIND_PIN) == 0)
superbitrf.status = SUPERBITRF_INIT_BINDING;
else
superbitrf.status = SUPERBITRF_INIT_TRANSFER;
}
break;
/* When the superbitrf is initializing binding */
case SUPERBITRF_INIT_BINDING:
// Try to write the binding config
if(cyrf6936_multi_write(&superbitrf.cyrf6936, cyrf_bind_config, 5))
superbitrf.status = SUPERBITRF_BINDING;
break;
/* When the superbitrf is in binding mode */
case SUPERBITRF_BINDING:
break;
/* Should not come here */
default:
break;
}
}
@@ -0,0 +1,86 @@
/*
* Copyright (C) 2013 Freek van Tienen <freek.v.tienen@gmail.com>
*
* This file is part of paparazzi.
*
* paparazzi 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, or (at your option)
* any later version.
*
* paparazzi 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 paparazzi; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
*/
/**
* @file subsystems/radio_control/superbitrf.h
* DSM2 and DSMX implementation for the cyrf6936 2.4GHz radio chip trough SPI
*/
#ifndef RADIO_CONTROL_SUPERBITRF_H
#define RADIO_CONTROL_SUPERBITRF_H
#include "peripherals/cyrf6936.h"
#include "mcu_periph/gpio.h"
/* Theoretically you could have 14 channel over DSM2/DSMX */
#ifndef RADIO_CONTROL_NB_CHANNEL
#define RADIO_CONTROL_NB_CHANNEL 14
#endif
/* The channel ordering is always the same for DSM2 and DSMX */
#define RADIO_THROTTLE 0
#define RADIO_ROLL 1
#define RADIO_PITCH 2
#define RADIO_YAW 3
#define RADIO_GEAR 4
#define RADIO_FLAP 5
#define RADIO_AUX1 5
#define RADIO_AUX2 6
#define RADIO_AUX3 7
#define RADIO_AUX4 8
#define RADIO_AUX5 9
#define RADIO_AUX6 10
#define RADIO_AUX7 11
#define RADIO_AUX8 12
#define RADIO_AUX9 13
/* Map the MODE default to the gear switch */
#ifndef RADIO_MODE
#define RADIO_MODE RADIO_GEAR
#endif
/* The different statuses the superbitRF can be in */
enum SuperbitRFStatus {
SUPERBITRF_UNINIT, /**< The chip isn't initialized */
SUPERBITRF_INIT_BINDING, /**< The chip is initializing binding mode */
SUPERBITRF_INIT_TRANSFER, /**< The chip is initializing transfer mode */
SUPERBITRF_BINDING, /**< The chip is in binding mode */
SUPERBITRF_TRANSFER, /**< The chip is in transfer mode */
};
/* The superbitrf structure */
struct SuperbitRF {
struct Cyrf6936 cyrf6936; /**< The cyrf chip used */
volatile enum SuperbitRFStatus status; /**< The status of the superbitRF */
};
/* The superbitrf functions and structures */
extern struct SuperbitRF superbitrf;
void superbitrf_event(void);
/* The radio control event handler */
#define RadioControlEvent(_received_frame_handler) { \
cyrf6936_event(&superbitrf.cyrf6936); \
superbitrf_event(); \
}
#endif /* RADIO_CONTROL_SUPERBITRF_H */