mirror of
https://github.com/paparazzi/paparazzi.git
synced 2026-06-04 22:17:01 +08:00
[superbitrf] Initial commit for superbitrf 2.4GHz radio control
This commit is contained in:
@@ -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
@@ -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"/>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
Reference in New Issue
Block a user