flipperzero-firmware/applications/cc1101-workaround/cc1101.cpp
coreglitch f5b342abbe
Api hw gpio pwm (#199)
* initial gpio layer

* move temlplate.c to template.c.example in preparing to applications.mk rework

* separate arduino layer

* separate flipper_hal.x

* prepare to switch applications on v2 core gpio api

* swithch applications to v2 gpio api

* gpio api for local target

* better gpio_disable handling

* remove pwm functions from local target

* inline gpio funcs

* common function to init all api's

* fix local example blink

* move delay us to hal api folder

* move pwm_set/pwm_stop to hal api folder

* update applications to use hal pwm api

* remove gpio mode case warning

* add speaker demo to build

Co-authored-by: DrZlo13 <who.just.the.doctor@gmail.com>
2020-10-26 10:16:54 +03:00

422 lines
14 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "flipper_v2.h"
#include "cc1101-workaround/cc1101.h"
// ******************************************************************************
#define WRITE_BURST 0x40
#define READ_SINGLE 0x80
#define READ_BURST 0xC0
#define BYTES_IN_FIFO 0x7F //used to detect FIFO underflow or overflow
/*********************ss_pin as global variable****************************** */
/* cc1101 */
/******************************************************************************/
GpioPin ss_pin;
CC1101::CC1101(GpioPin* ss_pin) {
/*
pinMode(gdo0_pin, OUTPUT); //GDO0 as asynchronous serial mode input
pinMode(gdo2_pin, INPUT); //GDO2 as asynchronous serial mode output
*/
pinMode(ss_pin, OUTPUT);
this->ss_pin = ss_pin;
// TODO open record
this->miso_pin = MISO_PIN;
this->miso_pin_record = &this->miso_pin;
}
//******************************************************************************
//SpiInit
/******************************************************************************/
extern SPI_HandleTypeDef hspi3;
void CC1101::SpiInit(void) {
//initialize spi pins
//Enable spi master, MSB, SPI mode 0, FOSC/4
SpiMode(0);
if(HAL_SPI_DeInit(&hspi3) != HAL_OK) {
Error_Handler();
}
hspi3.Init.Mode = SPI_MODE_MASTER;
hspi3.Init.Direction = SPI_DIRECTION_2LINES;
hspi3.Init.DataSize = SPI_DATASIZE_8BIT;
hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi3.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi3.Init.NSS = SPI_NSS_SOFT;
hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;
hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi3.Init.TIMode = SPI_TIMODE_DISABLE;
hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi3.Init.CRCPolynomial = 7;
hspi3.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi3.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
if(HAL_SPI_Init(&hspi3) != HAL_OK) {
Error_Handler();
}
}
void CC1101::SpiEnd(void) {
/*
SPCR = ((0<<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 0 = osc/4; 0 1 = osc/16; 1 0 = osc/64; 1 1= 0sc/128)
(0<<CPOL)| // Clock Polarity (0:SCK low / 1:SCK hi when idle)
(0<<CPHA)); // Clock Phase (0:leading / 1:trailing edge sampling)
//SPSR = (0<<SPI2X); // Double Clock Rate
*/
}
/******************************************************************************
Function: SpiMode
*INPUT : config mode
(0<<CPOL) | (0 << CPHA) 0
(0<<CPOL) | (1 << CPHA) 1
(1<<CPOL) | (0 << CPHA) 2
(1<<CPOL) | (1 << CPHA) 3
*OUTPUT :none
******************************************************************************/
void CC1101::SpiMode(byte config) {
/*
byte tmp;
// enable SPI master with configuration byte specified
SPCR = 0;
SPCR = (config & 0x7F) | (1<<SPE) | (1<<MSTR);
tmp = SPSR;
tmp = SPDR;
*/
}
/****************************************************************
*FUNCTION NAME:SpiTransfer
*FUNCTION :spi transfer
*INPUT :value: data to send
*OUTPUT :data to receive
****************************************************************/
byte CC1101::SpiTransfer(byte value) {
uint8_t buf[1] = {value};
uint8_t rxbuf[1] = {0};
HAL_SPI_TransmitReceive(&hspi3, buf, rxbuf, 1, HAL_MAX_DELAY);
return rxbuf[0];
}
/****************************************************************
*FUNCTION NAME:SpiWriteReg
*FUNCTION :CC1101 write data to register
*INPUT :addr: register address; value: register value
*OUTPUT :none
****************************************************************/
void CC1101::SpiWriteReg(byte addr, byte value) {
digitalWrite(ss_pin, LOW);
while(digitalRead(this->miso_pin_record))
;
SpiTransfer(addr);
SpiTransfer(value);
digitalWrite(ss_pin, HIGH);
}
/****************************************************************
*FUNCTION NAME:SpiWriteBurstReg
*FUNCTION :CC1101 write burst data to register
*INPUT :addr: register address; buffer:register value array; num:number to write
*OUTPUT :none
****************************************************************/
void CC1101::SpiWriteBurstReg(byte addr, byte* buffer, byte num) {
byte i, temp;
temp = addr | WRITE_BURST;
digitalWrite(ss_pin, LOW);
while(digitalRead(this->miso_pin_record))
;
SpiTransfer(temp);
for(i = 0; i < num; i++) {
SpiTransfer(buffer[i]);
}
digitalWrite(ss_pin, HIGH);
}
/****************************************************************
*FUNCTION NAME:SpiStrobe
*FUNCTION :CC1101 Strobe
*INPUT :strobe: command; //refer define in CC1101.h//
*OUTPUT :none
****************************************************************/
void CC1101::SpiStrobe(byte strobe) {
digitalWrite(ss_pin, LOW);
while(digitalRead(this->miso_pin_record))
;
SpiTransfer(strobe);
digitalWrite(ss_pin, HIGH);
}
/****************************************************************
*FUNCTION NAME:SpiReadReg
*FUNCTION :CC1101 read data from register
*INPUT :addr: register address
*OUTPUT :register value
****************************************************************/
byte CC1101::SpiReadReg(byte addr) {
byte temp, value;
temp = addr | READ_SINGLE;
digitalWrite(ss_pin, LOW);
while(digitalRead(this->miso_pin_record))
;
SpiTransfer(temp);
value = SpiTransfer(0);
digitalWrite(ss_pin, HIGH);
return value;
}
/****************************************************************
*FUNCTION NAME:SpiReadBurstReg
*FUNCTION :CC1101 read burst data from register
*INPUT :addr: register address; buffer:array to store register value; num: number to read
*OUTPUT :none
****************************************************************/
void CC1101::SpiReadBurstReg(byte addr, byte* buffer, byte num) {
byte i, temp;
temp = addr | READ_BURST;
digitalWrite(ss_pin, LOW);
while(digitalRead(this->miso_pin_record))
;
SpiTransfer(temp);
for(i = 0; i < num; i++) {
buffer[i] = SpiTransfer(0);
}
digitalWrite(ss_pin, HIGH);
}
/****************************************************************
*FUNCTION NAME:SpiReadStatus
*FUNCTION :CC1101 read status register
*INPUT :addr: register address
*OUTPUT :status value
****************************************************************/
byte CC1101::SpiReadStatus(byte addr) {
byte value, temp;
temp = addr | READ_BURST;
digitalWrite(ss_pin, LOW);
while(digitalRead(this->miso_pin_record))
;
SpiTransfer(temp);
value = SpiTransfer(0);
digitalWrite(ss_pin, HIGH);
return value;
}
/****************************************************************
*FUNCTION NAME:Reset
*FUNCTION :CC1101 reset //details refer datasheet of CC1101/CC1100//
*INPUT :none
*OUTPUT :none
****************************************************************/
void CC1101::Reset(void) {
digitalWrite(ss_pin, LOW);
delay(1);
digitalWrite(ss_pin, HIGH);
delay(1);
digitalWrite(ss_pin, LOW);
while(digitalRead(this->miso_pin_record))
;
SpiTransfer(CC1101_SRES);
while(digitalRead(this->miso_pin_record))
;
digitalWrite(ss_pin, HIGH);
}
/****************************************************************
*FUNCTION NAME:Init
*FUNCTION :CC1101 initialization
*INPUT :none
*OUTPUT :none
****************************************************************/
byte CC1101::Init(void) {
#ifdef CC1101_DEBUG
printf("Init SPI...\n");
#endif
SpiInit(); //spi initialization
digitalWrite(ss_pin, HIGH);
// digitalWrite(SCK_PIN, HIGH);
// digitalWrite(MOSI_PIN, LOW);
#ifdef CC1101_DEBUG
printf("Reset CC1101...\n");
#endif
Reset(); //CC1101 reset
byte partnum, version;
partnum = SpiReadStatus(CC1101_PARTNUM);
version = SpiReadStatus(CC1101_VERSION);
#ifdef CC1101_DEBUG
printf("Partnum:0x%02X, Version:0x%02X\n", partnum, version);
#endif
#ifdef CC1101_DEBUG
printf("Init CC1101...");
#endif
RegConfigSettings(); //CC1101 register config
#ifdef CC1101_DEBUG
printf("Done!\n");
#endif
return version;
}
/****************************************************************
*FUNCTION NAME:SetMod
*FUNCTION :CC1101 modulation type
*INPUT :byte mode
*OUTPUT :none
****************************************************************/
void CC1101::SetMod(byte mode) {
SpiWriteReg(CC1101_MDMCFG2, mode); //no sync/preamble; ASK/OOK only support up to -1dbm
if((mode | 0x30) == ASK) {
SpiWriteReg(CC1101_FREND0, 0x11); //use first up to PATABLE(0)
byte PaTabel[8] = {0x00, POWER, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
SpiWriteBurstReg(CC1101_PATABLE, PaTabel, 8); //CC1101 PATABLE config
} else {
SpiWriteReg(CC1101_FREND0, 0x10); //use first up to PATABLE(0)
byte PaTabel[8] = {POWER, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
SpiWriteBurstReg(CC1101_PATABLE, PaTabel, 8); //CC1101 PATABLE config
}
#ifdef CC1101_DEBUG
switch(mode | 0x30) {
case GFSK: {
printf("CC1101 Modulation: GFSK");
break;
}
case MSK: {
printf("CC1101 Modulation: MSK");
break;
}
case ASK: {
printf("CC1101 Modulation: ASK/OOK");
break;
}
case FSK2: {
printf("CC1101 Modulation: 2-FSK");
break;
}
case FSK4: {
printf("CC1101 Modulation: 4-FSK");
break;
}
default: //default to GFSK
{
printf("Modulation mode not supported");
break;
}
}
printf("\n");
#endif
}
/****************************************************************
*FUNCTION NAME:RegConfigSettings
*FUNCTION :CC1101 register config //details refer datasheet of CC1101/CC1100//
*INPUT :none
*OUTPUT :none
****************************************************************/
void CC1101::RegConfigSettings(void) {
SpiWriteReg(CC1101_FSCTRL1, 0x06); //IF frequency
SpiWriteReg(CC1101_FSCTRL0, 0x00); //frequency offset before synthesizer
SpiWriteReg(CC1101_MDMCFG4, 0xCC); // RX filter bandwidth 100k(0xcc)
SpiWriteReg(
CC1101_MDMCFG3, 0x43); //datarate config 512kBaud for the purpose of fast rssi measurement
SpiWriteReg(CC1101_MDMCFG1, 0x21); //FEC preamble etc. last 2 bits for channel spacing
SpiWriteReg(CC1101_MDMCFG0, 0xF8); //100khz channel spacing
//CC1101_CHANNR moved to SetChannel func
//SpiWriteReg(CC1101_DEVIATN, 0x47);
SpiWriteReg(
CC1101_MCSM0, 0x18); // calibrate when going from IDLE to RX or TX ; 149 - 155 μs timeout
SpiWriteReg(CC1101_FOCCFG, 0x16); //frequency compensation
//SpiWriteReg(CC1101_BSCFG, 0x1C); //bit synchronization config
SpiWriteReg(CC1101_AGCCTRL2, 0x43);
SpiWriteReg(CC1101_AGCCTRL1, 0x49);
SpiWriteReg(CC1101_AGCCTRL0, 0x91);
//freq synthesizer calibration
SpiWriteReg(CC1101_FSCAL3, 0xEA);
SpiWriteReg(CC1101_FSCAL2, 0x2A);
SpiWriteReg(CC1101_FSCAL1, 0x00);
SpiWriteReg(CC1101_FSCAL0, 0x1F);
SpiWriteReg(CC1101_TEST2, 0x81);
SpiWriteReg(CC1101_TEST1, 0x35);
SpiWriteReg(CC1101_TEST0, 0x0B); //should be 0x0B for lower than 430.6MHz and 0x09 for higher
//SpiWriteReg(CC1101_FREND1, 0x56);
//SpiWriteReg(CC1101_IOCFG2, 0x0B); //serial clock.synchronous to the data in synchronous serial mode
//SpiWriteReg(CC1101_IOCFG0, 0x06); //asserts when sync word has been sent/received, and de-asserts at the end of the packet
SpiWriteReg(CC1101_IOCFG2, 0x0D); //data output pin for asynchronous mode
SpiWriteReg(
CC1101_IOCFG0,
0x2E); //High impedance (3-state), GDO0 configed as data input for asynchronous mode
//SpiWriteReg(CC1101_PKTCTRL0, 0x05); //whitening off;CRC Enablevariable length packets, packet length configured by the first byte after sync word
SpiWriteReg(
CC1101_PKTCTRL0, 0x33); //whitening off; asynchronous serial mode; CRC diablereserved
//SpiWriteReg(CC1101_PKTLEN, 0x3D); //61 bytes max length
SpiWriteReg(
CC1101_FIFOTHR,
0x47); //Adc_retention enabled for RX filter bandwidth less than 325KHz; defalut fifo threthold.
}
/****************************************************************
*FUNCTION NAME:SetFreq
*FUNCTION :SetFreq
*INPUT :Freq2, Freq1, Freq0
*OUTPUT :none
****************************************************************/
void CC1101::SetFreq(byte freq2, byte freq1, byte freq0) {
SpiWriteReg(CC1101_FREQ2, freq2);
SpiWriteReg(CC1101_FREQ1, freq1);
SpiWriteReg(CC1101_FREQ0, freq0);
}
/****************************************************************
*FUNCTION NAME:SetChannel
*FUNCTION :SetChannel
*INPUT :int channel
*OUTPUT :none
****************************************************************/
void CC1101::SetChannel(int channel) {
#ifdef CC1101_DEBUG
printf("Set CC1101 channel to: %d \n", channel);
#endif
SpiWriteReg(CC1101_CHANNR, (byte)channel); //related to channel numbers
}
/****************************************************************
*FUNCTION NAME:SetReceive
*FUNCTION :SetReceive
*INPUT :none
*OUTPUT :none
****************************************************************/
void CC1101::SetReceive(void) {
SpiStrobe(CC1101_SRX);
while(SpiReadStatus(CC1101_MARCSTATE) ^ CC1101_STATUS_RX) {
// delay(1);
// printf("wait status\n");
}
}
/****************************************************************
*FUNCTION NAME:SetTransmit
*FUNCTION :
*INPUT :none
*OUTPUT :none
****************************************************************/
void CC1101::SetTransmit(void) {
SpiStrobe(CC1101_STX);
while(SpiReadStatus(CC1101_MARCSTATE) ^ CC1101_STATUS_TX)
;
}
//cc1101 cc1101;