[FL-950] CC1101 Stage1, SPI Refactoring, Drivers layer (#386)
* API HAL SPI: refactoring, split into layers, prepare ST HAL separation. API HAL SubGhz: initialize on start. Drivers: add basic cc1101 driver. Update API usage. Debug: increase max debugger port speed. Remove subghz apps. * CC1101: chip status handling. ApiHalSpi: increase SubGhz bus speed to 8mhz. F4: backport subghz initialization. * Api Hal SubGhz: rx path and frequency. CC1101: frequency control. * SubGhz Application: basic tests * SubGhz app: tone and packet test. API HAL SUBGHZ: update configs, add missing bits and pieces.
This commit is contained in:
parent
5309bfae41
commit
5439e232cc
@ -16,7 +16,6 @@ int32_t gui_task(void* p);
|
||||
int32_t backlight_control(void* p);
|
||||
int32_t irda(void* p);
|
||||
int32_t app_loader(void* p);
|
||||
int32_t cc1101_workaround(void* p);
|
||||
int32_t lf_rfid_workaround(void* p);
|
||||
int32_t nfc_task(void* p);
|
||||
int32_t dolphin_task(void* p);
|
||||
@ -31,7 +30,7 @@ int32_t music_player(void* p);
|
||||
int32_t sdnfc(void* p);
|
||||
int32_t floopper_bloopper(void* p);
|
||||
int32_t sd_filesystem(void* p);
|
||||
int32_t app_subghz(void* p);
|
||||
int32_t subghz_app(void* p);
|
||||
int32_t gui_test(void* p);
|
||||
int32_t keypad_test(void* p);
|
||||
|
||||
@ -82,13 +81,6 @@ const FlipperApplication FLIPPER_SERVICES[] = {
|
||||
{.app = bt_task, .name = "bt_task", .stack_size = 1024, .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_CC1101
|
||||
{.app = cc1101_workaround,
|
||||
.name = "cc1101 workaround",
|
||||
.stack_size = 1024,
|
||||
.icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_LF_RFID
|
||||
{.app = lf_rfid_workaround,
|
||||
.name = "lf rfid workaround",
|
||||
@ -151,10 +143,6 @@ const FlipperApplication FLIPPER_SERVICES[] = {
|
||||
{.app = gui_test, .name = "gui_test", .stack_size = 1024, .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_SUBGHZ
|
||||
{.app = app_subghz, .name = "app_subghz", .stack_size = 1024, .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_KEYPAD_TEST
|
||||
{.app = keypad_test, .name = "keypad_test", .icon = A_Plugins_14},
|
||||
#endif
|
||||
@ -164,8 +152,8 @@ const size_t FLIPPER_SERVICES_COUNT = sizeof(FLIPPER_SERVICES) / sizeof(FlipperA
|
||||
|
||||
// Main menu APP
|
||||
const FlipperApplication FLIPPER_APPS[] = {
|
||||
#ifdef BUILD_CC1101
|
||||
{.app = cc1101_workaround, .name = "Sub-1 GHz", .stack_size = 1024, .icon = A_Sub1ghz_14},
|
||||
#ifdef BUILD_SUBGHZ
|
||||
{.app = subghz_app, .name = "Sub-1 GHz", .stack_size = 1024, .icon = A_Sub1ghz_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_LF_RFID
|
||||
@ -228,10 +216,6 @@ const FlipperApplication FLIPPER_PLUGINS[] = {
|
||||
{.app = gui_test, .name = "gui_test", .stack_size = 1024, .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_SUBGHZ
|
||||
{.app = app_subghz, .name = "app_subghz", .stack_size = 1024, .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_KEYPAD_TEST
|
||||
{.app = keypad_test, .name = "keypad_test", .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
@ -20,7 +20,7 @@ APP_DOLPHIN = 1
|
||||
BUILD_EXAMPLE_BLINK = 1
|
||||
BUILD_EXAMPLE_UART_WRITE = 1
|
||||
BUILD_EXAMPLE_INPUT_DUMP = 1
|
||||
BUILD_CC1101 = 1
|
||||
BUILD_SUBGHZ = 1
|
||||
BUILD_LF_RFID = 1
|
||||
BUILD_SPEAKER_DEMO = 1
|
||||
BUILD_VIBRO_DEMO = 1
|
||||
@ -31,7 +31,6 @@ BUILD_FLOOPPER_BLOOPPER = 1
|
||||
BUILD_IBUTTON = 1
|
||||
BUILD_GUI_TEST = 1
|
||||
BUILD_KEYPAD_TEST = 1
|
||||
BUILD_SUBGHZ = 1
|
||||
endif
|
||||
|
||||
APP_NFC ?= 0
|
||||
@ -146,16 +145,9 @@ C_SOURCES += $(APP_DIR)/examples/u8g2_qrcode.c
|
||||
C_SOURCES += $(LIB_DIR)/qrcode/qrcode.c
|
||||
endif
|
||||
|
||||
APP_CC1101 ?= 0
|
||||
ifeq ($(APP_CC1101), 1)
|
||||
CFLAGS += -DAPP_CC1101
|
||||
BUILD_CC1101 = 1
|
||||
endif
|
||||
BUILD_CC1101 ?= 0
|
||||
ifeq ($(BUILD_CC1101), 1)
|
||||
CFLAGS += -DBUILD_CC1101
|
||||
C_SOURCES += $(wildcard $(APP_DIR)/cc1101-workaround/*.c)
|
||||
CPP_SOURCES += $(wildcard $(APP_DIR)/cc1101-workaround/*.cpp)
|
||||
ifeq ($(BUILD_SUBGHZ), 1)
|
||||
CFLAGS += -DBUILD_SUBGHZ
|
||||
C_SOURCES += $(wildcard $(APP_DIR)/subghz/*.c)
|
||||
APP_INPUT = 1
|
||||
APP_GUI = 1
|
||||
APP_CLI = 1
|
||||
@ -292,18 +284,6 @@ CFLAGS += -DBUILD_GUI_TEST
|
||||
C_SOURCES += $(wildcard $(APP_DIR)/gui-test/*.c)
|
||||
endif
|
||||
|
||||
APP_SUBGHZ ?= 0
|
||||
ifeq ($(APP_SUBGHZ), 1)
|
||||
CFLAGS += -DAPP_SUBGHZ
|
||||
BUILD_SUBGHZ = 1
|
||||
endif
|
||||
BUILD_SUBGHZ ?= 0
|
||||
ifeq ($(BUILD_SUBGHZ), 1)
|
||||
CFLAGS += -DBUILD_SUBGHZ
|
||||
CPP_SOURCES += $(wildcard $(APP_DIR)/subghz/*.cpp)
|
||||
CPP_SOURCES += $(wildcard $(APP_DIR)/subghz/*/*.cpp)
|
||||
endif
|
||||
|
||||
APP_SDNFC ?= 0
|
||||
ifeq ($(APP_SDNFC), 1)
|
||||
CFLAGS += -DAPP_SDNFC
|
||||
|
@ -1,614 +0,0 @@
|
||||
#include "cc1101.h"
|
||||
#include <furi.h>
|
||||
#include <api-hal.h>
|
||||
#include <gui/gui.h>
|
||||
#include <input/input.h>
|
||||
|
||||
#define RSSI_DELAY 5000 //rssi delay in micro second
|
||||
#define CHAN_SPA 0.05 // channel spacing
|
||||
|
||||
int16_t rssi_to_dbm(uint8_t rssi_dec, uint8_t rssiOffset) {
|
||||
int16_t rssi;
|
||||
|
||||
if(rssi_dec >= 128) {
|
||||
rssi = (int16_t)((int16_t)(rssi_dec - 256) / 2) - rssiOffset;
|
||||
} else {
|
||||
rssi = (rssi_dec / 2) - rssiOffset;
|
||||
}
|
||||
|
||||
return rssi;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
float base_freq;
|
||||
uint8_t reg[3]; // FREQ2, FREQ1, FREQ0
|
||||
uint8_t first_channel;
|
||||
uint8_t last_channel;
|
||||
uint8_t rssi_offset;
|
||||
} Band;
|
||||
|
||||
typedef struct {
|
||||
const Band* band;
|
||||
uint16_t channel;
|
||||
} FreqConfig;
|
||||
|
||||
void setup_freq(CC1101* cc1101, float freq) {
|
||||
// cc1101->SpiWriteReg(CC1101_MCSM0, 0x08); // disalbe FS_AUTOCAL
|
||||
// cc1101->SpiWriteReg(CC1101_AGCCTRL2, 0x43 | 0x0C); // MAX_DVGA_GAIN to 11 for fast rssi
|
||||
// cc1101->SpiWriteReg(CC1101_AGCCTRL0, 0xB0); // max AGC WAIT_TIME; 0 filter_length
|
||||
// cc1101->SetMod(GFSK); // set to GFSK for fast rssi measurement | +8 is dcfilter off
|
||||
|
||||
uint32_t freq_reg = freq * 1e6 / (F_OSC / 65536);
|
||||
cc1101->SetFreq((freq_reg >> 16) & 0xFF, (freq_reg >> 8) & 0xFF, (freq_reg)&0xFF);
|
||||
cc1101->SetChannel(0);
|
||||
|
||||
/*
|
||||
//set test0 to 0x09
|
||||
cc1101->SpiWriteReg(CC1101_TEST0, 0x09);
|
||||
//set FSCAL2 to 0x2A to force VCO HIGH
|
||||
cc1101->SpiWriteReg(CC1101_FSCAL2, 0x2A);
|
||||
|
||||
// perform a manual calibration by issuing SCAL command
|
||||
cc1101->SpiStrobe(CC1101_SCAL);
|
||||
*/
|
||||
}
|
||||
|
||||
static GpioPin debug_0 = {GPIOB, GPIO_PIN_2};
|
||||
|
||||
int16_t rx_rssi(CC1101* cc1101, const FreqConfig* config) {
|
||||
// cc1101->SpiStrobe(CC1101_SFRX);
|
||||
// cc1101->SetReceive();
|
||||
|
||||
// uint8_t begin_size = cc1101->SpiReadStatus(CC1101_RXBYTES);
|
||||
// uint8_t rx_status = cc1101->SpiReadStatus(CC1101_MARCSTATE);
|
||||
|
||||
// delay_us(RSSI_DELAY);
|
||||
// osDelay(15);
|
||||
|
||||
// uint8_t end_size = cc1101->SpiReadStatus(CC1101_RXBYTES);
|
||||
|
||||
// 1.4.8) read PKTSTATUS register while the radio is in RX state
|
||||
/*uint8_t _pkt_status = */ // cc1101->SpiReadStatus(CC1101_PKTSTATUS);
|
||||
|
||||
// 1.4.9) enter IDLE state by issuing a SIDLE command
|
||||
// cc1101->SpiStrobe(CC1101_SIDLE);
|
||||
|
||||
// //read rssi value and converto to dBm form
|
||||
uint8_t rssi_dec = (uint8_t)cc1101->SpiReadStatus(CC1101_RSSI);
|
||||
int16_t rssi_dBm = rssi_to_dbm(rssi_dec, config->band->rssi_offset);
|
||||
|
||||
/*
|
||||
char buf[256];
|
||||
sprintf(buf, "status: %d -> %d, rssi: %d\n", rx_status, cc1101->SpiReadStatus(CC1101_MARCSTATE), rssi_dBm);
|
||||
printf(buf);
|
||||
sprintf(buf, "begin: %d, end: %d\n", begin_size, end_size);
|
||||
printf(buf);
|
||||
*/
|
||||
|
||||
// uint8_t rx_data[64];
|
||||
// uint8_t fifo_length = end_size - begin_size;
|
||||
|
||||
/*
|
||||
if(fifo_length < 64) {
|
||||
// cc1101->SpiReadBurstReg(CC1101_RXFIFO, rx_data, fifo_length);
|
||||
|
||||
*
|
||||
printf("FIFO:");
|
||||
for(uint8_t i = 0; i < fifo_length; i++) {
|
||||
for(uint8_t bit = 0; bit < 8; bit++) {
|
||||
printf("%s", (rx_data[i] & (1 << bit)) > 0 ? "1" : "0");
|
||||
}
|
||||
printf(" ");
|
||||
}
|
||||
printf("\r\n");
|
||||
*
|
||||
|
||||
for(uint8_t i = 0; i < fifo_length; i++) {
|
||||
for(uint8_t bit = 0; bit < 8; bit++) {
|
||||
gpio_write((GpioPin*)&debug_0, (rx_data[i] & (1 << bit)) > 0);
|
||||
delay_us(5);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printf("fifo size over\r\n");
|
||||
}
|
||||
*/
|
||||
|
||||
return rssi_dBm;
|
||||
}
|
||||
|
||||
/*
|
||||
void flp_config(CC1101* cc1101) {
|
||||
cc1101->SpiWriteReg(
|
||||
CC1101_MCSM0, 0x18); // calibrate when going from IDLE to RX or TX ; 149 - 155 μs timeout
|
||||
// MCSM0.FS_AUTOCAL[1:0] = 1
|
||||
|
||||
cc1101->SpiWriteReg(CC1101_AGCCTRL2, 0x43);
|
||||
cc1101->SpiWriteReg(CC1101_AGCCTRL1, 0x49);
|
||||
cc1101->SpiWriteReg(CC1101_AGCCTRL0, 0x91);
|
||||
|
||||
//freq synthesizer calibration
|
||||
cc1101->SpiWriteReg(CC1101_FSCAL3, 0xEA);
|
||||
cc1101->SpiWriteReg(CC1101_FSCAL2, 0x2A);
|
||||
cc1101->SpiWriteReg(CC1101_FSCAL1, 0x00);
|
||||
cc1101->SpiWriteReg(CC1101_FSCAL0, 0x1F);
|
||||
|
||||
// async data out
|
||||
cc1101->SpiSetRegValue(CC1101_IOCFG0, 13, 5, 0); // GDO0 Output Pin Configuration
|
||||
cc1101->SpiSetRegValue(CC1101_IOCFG0, 13, 5, 0); // WAT
|
||||
|
||||
// FIFOTHR.ADC_RETENTION = 1
|
||||
cc1101->SpiSetRegValue(CC1101_FIFOTHR, 1, 6, 6);
|
||||
|
||||
// PKTCTRL1.APPEND_STATUS = 0
|
||||
cc1101->SpiSetRegValue(CC1101_PKTCTRL1, 0, 2, 2);
|
||||
|
||||
// PKTCTRL0.WHITE_DATA = 0
|
||||
cc1101->SpiSetRegValue(CC1101_PKTCTRL0, 0, 6, 6);
|
||||
|
||||
// PKTCTRL0.LENGTH_CONFIG = 2 // Infinite packet length mode
|
||||
cc1101->SpiSetRegValue(CC1101_PKTCTRL0, 2, 1, 0);
|
||||
|
||||
// PKTCTRL0.CRC_EN = 0
|
||||
cc1101->SpiSetRegValue(CC1101_PKTCTRL0, 0, 2, 2);
|
||||
|
||||
// PKTCTRL0.PKT_FORMAT = 3
|
||||
cc1101->SpiSetRegValue(CC1101_PKTCTRL0, 3, 5, 4);
|
||||
|
||||
// bandwidth 50-100 kHz
|
||||
if(!cc1101->setRxBandwidth(75.0)) {
|
||||
printf("wrong rx bw\r\n");
|
||||
}
|
||||
|
||||
// datarate ~30 kbps
|
||||
if(!cc1101->setBitRate(100.)) {
|
||||
printf("wrong bitrate\r\n");
|
||||
}
|
||||
|
||||
// mod
|
||||
// MDMCFG2.MOD_FORMAT = 3 (3: OOK, 0: 2-FSK)
|
||||
cc1101->SpiSetRegValue(CC1101_MDMCFG2, 3, 6, 4);
|
||||
// MDMCFG2.SYNC_MODE = 0
|
||||
cc1101->SpiSetRegValue(CC1101_MDMCFG2, 0, 2, 0);
|
||||
}
|
||||
*/
|
||||
|
||||
void tx_config(CC1101* cc1101) {
|
||||
// cc1101->SpiWriteReg(CC1101_IOCFG2,0x0B); //GDO2 Output Pin Configuration
|
||||
// cc1101->SpiWriteReg(CC1101_IOCFG0,0x0C); //GDO0 Output Pin Configuration
|
||||
cc1101->SpiSetRegValue(CC1101_IOCFG0, 13, 5, 0); // GDO0 Output Pin Configuration
|
||||
|
||||
cc1101->SpiWriteReg(CC1101_FIFOTHR, 0x47); //RX FIFO and TX FIFO Thresholds
|
||||
cc1101->SpiWriteReg(CC1101_PKTCTRL0, 0x32); //Packet Automation Control
|
||||
cc1101->SpiWriteReg(CC1101_FSCTRL1, 0x06); //Frequency Synthesizer Control
|
||||
cc1101->SpiWriteReg(CC1101_FREQ2, 0x10); //Frequency Control Word, High Byte
|
||||
cc1101->SpiWriteReg(CC1101_FREQ1, 0xB0); //Frequency Control Word, Middle Byte
|
||||
cc1101->SpiWriteReg(CC1101_FREQ0, 0x71); //Frequency Control Word, Low Byte
|
||||
cc1101->SpiWriteReg(CC1101_MDMCFG4, 0x6A); //Modem Configuration
|
||||
cc1101->SpiWriteReg(CC1101_MDMCFG3, 0x2E); //Modem Configuration
|
||||
cc1101->SpiWriteReg(CC1101_MDMCFG2, 0x30); //Modem Configuration
|
||||
cc1101->SpiWriteReg(CC1101_DEVIATN, 0x15); //Modem Deviation Setting
|
||||
cc1101->SpiWriteReg(CC1101_MCSM0, 0x18); //Main Radio Control State Machine Configuration
|
||||
cc1101->SpiWriteReg(CC1101_FOCCFG, 0x16); //Frequency Offset Compensation Configuration
|
||||
cc1101->SpiWriteReg(CC1101_WORCTRL, 0xFB); //Wake On Radio Control
|
||||
cc1101->SpiWriteReg(CC1101_FREND0, 0x11); //Front End TX Configuration
|
||||
cc1101->SpiWriteReg(CC1101_FSCAL3, 0xE9); //Frequency Synthesizer Calibration
|
||||
cc1101->SpiWriteReg(CC1101_FSCAL2, 0x2A); //Frequency Synthesizer Calibration
|
||||
cc1101->SpiWriteReg(CC1101_FSCAL1, 0x00); //Frequency Synthesizer Calibration
|
||||
cc1101->SpiWriteReg(CC1101_FSCAL0, 0x1F); //Frequency Synthesizer Calibration
|
||||
|
||||
/*
|
||||
cc1101->SpiWriteReg(CC1101_TEST2, 0x81); //Various Test Settings
|
||||
cc1101->SpiWriteReg(CC1101_TEST1, 0x35); //Various Test Settings
|
||||
cc1101->SpiWriteReg(CC1101_TEST0, 0x09); //Various Test Settings
|
||||
*/
|
||||
}
|
||||
|
||||
// f = (f_osc/65536) * (FREQ + CHAN * (256 + CH_SP_M) * 2^(CH_SP_E - 2))
|
||||
// FREQ = f / (f_osc/65536)
|
||||
// CHAN = 0
|
||||
// TODO: CHAN number not implemented!
|
||||
// TODO: reg values not affetcts
|
||||
|
||||
const Band bands[] = {
|
||||
{301., {0x00, 0x00, 0x00}, 0, 255, 74},
|
||||
{315., {0x00, 0x00, 0x00}, 0, 255, 74},
|
||||
{346., {0x00, 0x00, 0x00}, 0, 255, 74},
|
||||
{385., {0x00, 0x00, 0x00}, 0, 255, 74},
|
||||
{433.92, {0x00, 0x00, 0x00}, 0, 255, 74},
|
||||
{438.9, {0x00, 0x00, 0x00}, 0, 255, 74},
|
||||
{463., {0x00, 0x00, 0x00}, 0, 255, 74},
|
||||
{781., {0x00, 0x00, 0x00}, 0, 255, 74},
|
||||
{868., {0x00, 0x00, 0x00}, 0, 255, 74},
|
||||
{915., {0x00, 0x00, 0x00}, 0, 255, 74},
|
||||
{925., {0x00, 0x00, 0x00}, 0, 255, 74},
|
||||
};
|
||||
|
||||
const FreqConfig FREQ_LIST[] = {
|
||||
{&bands[0], 0},
|
||||
{&bands[1], 0},
|
||||
{&bands[2], 0},
|
||||
{&bands[3], 0},
|
||||
{&bands[4], 0},
|
||||
{&bands[5], 0},
|
||||
{&bands[6], 0},
|
||||
{&bands[7], 0},
|
||||
{&bands[8], 0},
|
||||
{&bands[9], 0},
|
||||
{&bands[10], 0},
|
||||
};
|
||||
|
||||
extern "C" void cc1101_isr(void* _pin, void* _ctx) {
|
||||
uint32_t pin = (uint32_t)_pin;
|
||||
if(pin == CC1101_G0_Pin) {
|
||||
gpio_write((GpioPin*)&debug_0, gpio_read(&cc1101_g0_gpio));
|
||||
}
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
EventTypeTick,
|
||||
EventTypeKey,
|
||||
} EventType;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
InputEvent input;
|
||||
} value;
|
||||
EventType type;
|
||||
} AppEvent;
|
||||
|
||||
typedef enum { ModeRx, ModeTx } Mode;
|
||||
|
||||
typedef struct {
|
||||
int16_t dbm;
|
||||
uint8_t reg;
|
||||
} TxLevel;
|
||||
|
||||
const TxLevel TX_LEVELS[] = {
|
||||
{-10, 0},
|
||||
{-5, 0},
|
||||
{0, 0},
|
||||
{5, 0},
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
Mode mode;
|
||||
size_t active_freq_idx;
|
||||
float active_freq;
|
||||
int16_t last_rssi;
|
||||
size_t tx_level;
|
||||
bool need_cc1101_conf;
|
||||
RfBand rf_band;
|
||||
} State;
|
||||
|
||||
static void render_callback(Canvas* canvas, void* ctx) {
|
||||
State* state = (State*)acquire_mutex((ValueMutex*)ctx, 25);
|
||||
|
||||
if(!state) return;
|
||||
|
||||
canvas_clear(canvas);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str(canvas, 2, 12, "cc1101 workaround");
|
||||
|
||||
{
|
||||
char buf[24];
|
||||
sprintf(
|
||||
buf,
|
||||
"freq: %ld.%02ld MHz",
|
||||
(uint32_t)state->active_freq,
|
||||
(uint32_t)(state->active_freq * 100.) % 100);
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str(canvas, 2, 25, buf);
|
||||
}
|
||||
|
||||
{
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
|
||||
if(state->need_cc1101_conf) {
|
||||
canvas_draw_str(canvas, 2, 36, "mode: configuring...");
|
||||
} else if(state->mode == ModeRx) {
|
||||
canvas_draw_str(canvas, 2, 36, "mode: RX");
|
||||
} else if(state->mode == ModeTx) {
|
||||
canvas_draw_str(canvas, 2, 36, "mode: TX");
|
||||
} else {
|
||||
canvas_draw_str(canvas, 2, 36, "mode: unknown");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if(!state->need_cc1101_conf && state->mode == ModeRx) {
|
||||
char buf[24];
|
||||
sprintf(buf, "RSSI: %d dBm", state->last_rssi);
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str(canvas, 2, 48, buf);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
char buf[24];
|
||||
// sprintf(buf, "tx level: %d dBm", TX_LEVELS[state->tx_level].dbm);
|
||||
sprintf(buf, "RF band: %d", (uint8_t)state->rf_band);
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
if(state->rf_band == RfBandIsolation) {
|
||||
canvas_draw_str(canvas, 2, 63, "RF band: isolation");
|
||||
} else {
|
||||
canvas_draw_str(canvas, 2, 63, buf);
|
||||
}
|
||||
}
|
||||
|
||||
release_mutex((ValueMutex*)ctx, state);
|
||||
}
|
||||
|
||||
static void input_callback(InputEvent* input_event, void* ctx) {
|
||||
osMessageQueueId_t event_queue = ctx;
|
||||
|
||||
AppEvent event;
|
||||
event.type = EventTypeKey;
|
||||
event.value.input = *input_event;
|
||||
osMessageQueuePut(event_queue, &event, 0, 0);
|
||||
}
|
||||
|
||||
extern "C" int32_t cc1101_workaround(void* p) {
|
||||
osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(AppEvent), NULL);
|
||||
furi_check(event_queue);
|
||||
|
||||
State _state;
|
||||
_state.mode = ModeRx;
|
||||
_state.active_freq_idx = 4;
|
||||
|
||||
FreqConfig conf = FREQ_LIST[_state.active_freq_idx];
|
||||
_state.active_freq = conf.band->base_freq + CHAN_SPA * conf.channel;
|
||||
|
||||
_state.need_cc1101_conf = true;
|
||||
_state.last_rssi = 0;
|
||||
_state.tx_level = 0;
|
||||
_state.rf_band = RfBand1;
|
||||
|
||||
ValueMutex state_mutex;
|
||||
if(!init_mutex(&state_mutex, &_state, sizeof(State))) {
|
||||
printf("[cc1101] cannot create mutex\r\n");
|
||||
return 255;
|
||||
}
|
||||
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
|
||||
view_port_draw_callback_set(view_port, render_callback, &state_mutex);
|
||||
view_port_input_callback_set(view_port, input_callback, event_queue);
|
||||
|
||||
// Open GUI and register view_port
|
||||
Gui* gui = (Gui*)furi_record_open("gui");
|
||||
if(gui == NULL) {
|
||||
printf("[cc1101] gui is not available\r\n");
|
||||
return 255;
|
||||
}
|
||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||
|
||||
gpio_init(&debug_0, GpioModeOutputPushPull);
|
||||
gpio_write((GpioPin*)&debug_0, false);
|
||||
|
||||
printf("[cc1101] creating device\r\n");
|
||||
GpioPin cs_pin = {CC1101_CS_GPIO_Port, CC1101_CS_Pin};
|
||||
|
||||
gpio_init(&cc1101_g0_gpio, GpioModeInput);
|
||||
api_interrupt_add(cc1101_isr, InterruptTypeExternalInterrupt, NULL);
|
||||
// TODO open record
|
||||
GpioPin* cs_pin_record = &cs_pin;
|
||||
CC1101 cc1101(cs_pin_record);
|
||||
printf("[cc1101] init device\r\n");
|
||||
|
||||
uint8_t address = cc1101.Init();
|
||||
if(address > 0) {
|
||||
printf("[cc1101] init done: %d\r\n", address);
|
||||
} else {
|
||||
printf("[cc1101] init fail\r\n");
|
||||
return 255;
|
||||
}
|
||||
|
||||
cc1101.SpiStrobe(CC1101_SIDLE);
|
||||
|
||||
// flp_config(&cc1101);
|
||||
tx_config(&cc1101);
|
||||
// setup_freq(&cc1101, &FREQ_LIST[4]);
|
||||
// enable_cc1101_irq();
|
||||
|
||||
printf("init ok\r\n");
|
||||
|
||||
const int16_t RSSI_THRESHOLD = -60;
|
||||
|
||||
// setup_freq(&cc1101, &FREQ_LIST[1]);
|
||||
|
||||
cc1101.SetReceive();
|
||||
|
||||
AppEvent event;
|
||||
while(1) {
|
||||
osStatus_t event_status = osMessageQueueGet(event_queue, &event, NULL, 100);
|
||||
State* state = (State*)acquire_mutex_block(&state_mutex);
|
||||
|
||||
if(event_status == osOK) {
|
||||
if(event.type == EventTypeKey) {
|
||||
if(event.value.input.type == InputTypeShort &&
|
||||
event.value.input.key == InputKeyBack) {
|
||||
printf("[cc1101] bye!\r\n");
|
||||
|
||||
cc1101.SpiStrobe(CC1101_SIDLE);
|
||||
cc1101.SpiStrobe(CC1101_SPWD);
|
||||
|
||||
printf("[cc1101] go to power down\r\n");
|
||||
|
||||
// TODO remove all view_ports create by app
|
||||
view_port_enabled_set(view_port, false);
|
||||
return 255;
|
||||
}
|
||||
|
||||
if(event.value.input.type == InputTypeShort &&
|
||||
event.value.input.key == InputKeyDown) {
|
||||
if(state->active_freq_idx > 0) {
|
||||
state->active_freq_idx--;
|
||||
}
|
||||
|
||||
FreqConfig conf = FREQ_LIST[state->active_freq_idx];
|
||||
state->active_freq = conf.band->base_freq + CHAN_SPA * conf.channel;
|
||||
state->need_cc1101_conf = true;
|
||||
}
|
||||
|
||||
if(event.value.input.type == InputTypeShort &&
|
||||
event.value.input.key == InputKeyUp) {
|
||||
if(state->active_freq_idx < (sizeof(FREQ_LIST) / sizeof(FREQ_LIST[0]) - 1)) {
|
||||
state->active_freq_idx++;
|
||||
}
|
||||
|
||||
FreqConfig conf = FREQ_LIST[state->active_freq_idx];
|
||||
state->active_freq = conf.band->base_freq + CHAN_SPA * conf.channel;
|
||||
state->need_cc1101_conf = true;
|
||||
}
|
||||
|
||||
if(event.value.input.type == InputTypeShort &&
|
||||
event.value.input.key == InputKeyRight) {
|
||||
/*
|
||||
if(state->tx_level < (sizeof(TX_LEVELS) / sizeof(TX_LEVELS[0]) - 1)) {
|
||||
state->tx_level++;
|
||||
} else {
|
||||
state->tx_level = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
if(state->rf_band < RfBand3) {
|
||||
state->rf_band = (RfBand)((uint8_t)state->rf_band + 1);
|
||||
} else {
|
||||
state->active_freq += 0.25;
|
||||
}
|
||||
state->need_cc1101_conf = true;
|
||||
}
|
||||
|
||||
if(event.value.input.type == InputTypeShort &&
|
||||
event.value.input.key == InputKeyLeft) {
|
||||
/*
|
||||
if(state->tx_level < (sizeof(TX_LEVELS) / sizeof(TX_LEVELS[0]) - 1)) {
|
||||
state->tx_level++;
|
||||
} else {
|
||||
state->tx_level = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
if(state->rf_band > RfBandIsolation) {
|
||||
state->rf_band = (RfBand)((uint8_t)state->rf_band - 1);
|
||||
} else {
|
||||
state->active_freq -= 0.25;
|
||||
}
|
||||
state->need_cc1101_conf = true;
|
||||
}
|
||||
|
||||
if(event.value.input.key == InputKeyOk) {
|
||||
if(event.value.input.type == InputTypePress) {
|
||||
state->mode = ModeTx;
|
||||
state->need_cc1101_conf = true;
|
||||
} else if(event.value.input.type == InputTypeRelease) {
|
||||
state->mode = ModeRx;
|
||||
state->need_cc1101_conf = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
|
||||
if(state->need_cc1101_conf) {
|
||||
if(state->mode == ModeRx) {
|
||||
cc1101.SpiStrobe(CC1101_SIDLE);
|
||||
gpio_init(&cc1101_g0_gpio, GpioModeInput);
|
||||
|
||||
setup_freq(&cc1101, state->active_freq);
|
||||
cc1101.SetReceive();
|
||||
|
||||
state->last_rssi = rx_rssi(&cc1101, &FREQ_LIST[state->active_freq_idx]);
|
||||
} else if(state->mode == ModeTx) {
|
||||
cc1101.SpiStrobe(CC1101_SIDLE);
|
||||
|
||||
setup_freq(&cc1101, state->active_freq);
|
||||
cc1101.SetTransmit();
|
||||
gpio_init(&cc1101_g0_gpio, GpioModeOutputPushPull);
|
||||
gpio_write(&cc1101_g0_gpio, false);
|
||||
}
|
||||
|
||||
api_hal_rf_band_set(state->rf_band);
|
||||
|
||||
state->need_cc1101_conf = false;
|
||||
}
|
||||
|
||||
if(!state->need_cc1101_conf && state->mode == ModeRx) {
|
||||
// TOOD what about rssi offset
|
||||
state->last_rssi = rx_rssi(&cc1101, &FREQ_LIST[state->active_freq_idx]);
|
||||
|
||||
api_hal_light_set(LightGreen, state->last_rssi > RSSI_THRESHOLD ? 0xFF : 0x00);
|
||||
} else if(!state->need_cc1101_conf && state->mode == ModeTx) {
|
||||
/*
|
||||
const uint8_t data = 0xA5;
|
||||
|
||||
for(uint8_t i = 0; i < 8; i++) {
|
||||
gpio_write(&cc1101_g0_gpio, (data & (1 << i)) > 0);
|
||||
osDelay(1);
|
||||
}
|
||||
gpio_write(&cc1101_g0_gpio, false);
|
||||
*/
|
||||
|
||||
/*
|
||||
// BELL UDB-Q022-0000
|
||||
const uint16_t HALF_PERIOD = 500;
|
||||
|
||||
for(uint8_t n = 0; n < 4; n++) {
|
||||
for(uint8_t i = 0; i < 4; i++) {
|
||||
gpio_write(&cc1101_g0_gpio, true);
|
||||
delay_us(3 * HALF_PERIOD);
|
||||
gpio_write(&cc1101_g0_gpio, false);
|
||||
delay_us(HALF_PERIOD);
|
||||
}
|
||||
|
||||
for(uint8_t i = 0; i < 40; i++) {
|
||||
gpio_write(&cc1101_g0_gpio, true);
|
||||
delay_us(HALF_PERIOD);
|
||||
gpio_write(&cc1101_g0_gpio, false);
|
||||
delay_us(HALF_PERIOD);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// BELL ERA C61, static code
|
||||
const uint16_t ONE_ON = 150;
|
||||
const uint16_t ONE_OFF = 400;
|
||||
const uint16_t ZERO_ON = 420;
|
||||
const uint16_t ZERO_OFF = 130;
|
||||
|
||||
const bool SEQ[] = {true, true, false, false, true, false, true, false, true,
|
||||
false, true, true, true, false, true, false, true, true,
|
||||
true, true, true, false, true, false, true};
|
||||
|
||||
for(uint8_t n = 0; n < 10; n++) {
|
||||
for(uint8_t i = 0; i < sizeof(SEQ) / sizeof(SEQ[0]); i++) {
|
||||
if(SEQ[i]) {
|
||||
gpio_write(&cc1101_g0_gpio, false);
|
||||
delay_us(ONE_ON);
|
||||
gpio_write(&cc1101_g0_gpio, true);
|
||||
delay_us(ONE_OFF);
|
||||
} else {
|
||||
gpio_write(&cc1101_g0_gpio, false);
|
||||
delay_us(ZERO_ON);
|
||||
gpio_write(&cc1101_g0_gpio, true);
|
||||
delay_us(ZERO_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
osDelay(4);
|
||||
}
|
||||
|
||||
gpio_write(&cc1101_g0_gpio, false);
|
||||
}
|
||||
|
||||
release_mutex(&state_mutex, state);
|
||||
view_port_update(view_port);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,485 +0,0 @@
|
||||
#include <furi.h>
|
||||
#include <api-hal.h>
|
||||
|
||||
#include "cc1101-workaround/cc1101.h"
|
||||
#include "spi.h"
|
||||
#include <math.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
|
||||
*/
|
||||
gpio_init(ss_pin, GpioModeOutputPushPull);
|
||||
this->ss_pin = ss_pin;
|
||||
|
||||
// TODO open record
|
||||
this->miso_pin = MISO_PIN;
|
||||
this->miso_pin_record = &this->miso_pin;
|
||||
}
|
||||
//******************************************************************************
|
||||
//SpiInit
|
||||
/******************************************************************************/
|
||||
extern SPI_HandleTypeDef SPI_R;
|
||||
void CC1101::SpiInit(void) {
|
||||
//initialize spi pins
|
||||
|
||||
//Enable spi master, MSB, SPI mode 0, FOSC/4
|
||||
SpiMode(0);
|
||||
|
||||
CC1101_SPI_Reconfigure();
|
||||
}
|
||||
|
||||
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(uint8_t config) {
|
||||
/*
|
||||
uint8_t 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
|
||||
****************************************************************/
|
||||
uint8_t CC1101::SpiTransfer(uint8_t value) {
|
||||
uint8_t buf[1] = {value};
|
||||
uint8_t rxbuf[1] = {0};
|
||||
|
||||
HAL_SPI_TransmitReceive(&SPI_R, buf, rxbuf, 1, HAL_MAX_DELAY);
|
||||
|
||||
return rxbuf[0];
|
||||
}
|
||||
|
||||
uint8_t last_status;
|
||||
|
||||
/****************************************************************
|
||||
*FUNCTION NAME:SpiWriteReg
|
||||
*FUNCTION :CC1101 write data to register
|
||||
*INPUT :addr: register address; value: register value
|
||||
*OUTPUT :none
|
||||
****************************************************************/
|
||||
void CC1101::SpiWriteReg(uint8_t addr, uint8_t value) {
|
||||
gpio_write(ss_pin, false);
|
||||
while(gpio_read(this->miso_pin_record))
|
||||
;
|
||||
|
||||
last_status = SpiTransfer(addr);
|
||||
last_status = SpiTransfer(value);
|
||||
gpio_write(ss_pin, true);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
*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(uint8_t addr, uint8_t* buffer, uint8_t num) {
|
||||
gpio_write(ss_pin, false);
|
||||
while(gpio_read(this->miso_pin_record))
|
||||
;
|
||||
last_status = SpiTransfer(addr | WRITE_BURST);
|
||||
for(uint8_t i = 0; i < num; i++) {
|
||||
last_status = SpiTransfer(buffer[i]);
|
||||
}
|
||||
gpio_write(ss_pin, true);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
*FUNCTION NAME:SpiStrobe
|
||||
*FUNCTION :CC1101 Strobe
|
||||
*INPUT :strobe: command; //refer define in CC1101.h//
|
||||
*OUTPUT :none
|
||||
****************************************************************/
|
||||
void CC1101::SpiStrobe(uint8_t strobe) {
|
||||
gpio_write(ss_pin, false);
|
||||
while(gpio_read(this->miso_pin_record))
|
||||
;
|
||||
last_status = SpiTransfer(strobe);
|
||||
gpio_write(ss_pin, true);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
*FUNCTION NAME:SpiReadReg
|
||||
*FUNCTION :CC1101 read data from register
|
||||
*INPUT :addr: register address
|
||||
*OUTPUT :register value
|
||||
****************************************************************/
|
||||
uint8_t CC1101::SpiReadReg(uint8_t addr) {
|
||||
gpio_write(ss_pin, false);
|
||||
while(gpio_read(this->miso_pin_record))
|
||||
;
|
||||
last_status = SpiTransfer(addr | READ_SINGLE);
|
||||
uint8_t value = SpiTransfer(0);
|
||||
gpio_write(ss_pin, true);
|
||||
|
||||
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(uint8_t addr, uint8_t* buffer, uint8_t num) {
|
||||
gpio_write(ss_pin, false);
|
||||
while(gpio_read(this->miso_pin_record))
|
||||
;
|
||||
last_status = SpiTransfer(addr | READ_BURST);
|
||||
for(uint8_t i = 0; i < num; i++) {
|
||||
buffer[i] = SpiTransfer(0);
|
||||
}
|
||||
gpio_write(ss_pin, true);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
*FUNCTION NAME:SpiReadStatus
|
||||
*FUNCTION :CC1101 read status register
|
||||
*INPUT :addr: register address
|
||||
*OUTPUT :status value
|
||||
****************************************************************/
|
||||
uint8_t CC1101::SpiReadStatus(uint8_t addr) {
|
||||
gpio_write(ss_pin, false);
|
||||
while(gpio_read(this->miso_pin_record))
|
||||
;
|
||||
last_status = SpiTransfer(addr | READ_BURST);
|
||||
uint8_t value = SpiTransfer(0);
|
||||
gpio_write(ss_pin, true);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
*FUNCTION NAME:Reset
|
||||
*FUNCTION :CC1101 reset //details refer datasheet of CC1101/CC1100//
|
||||
*INPUT :none
|
||||
*OUTPUT :none
|
||||
****************************************************************/
|
||||
void CC1101::Reset(void) {
|
||||
gpio_write(ss_pin, false);
|
||||
delay(1);
|
||||
gpio_write(ss_pin, true);
|
||||
delay(1);
|
||||
gpio_write(ss_pin, false);
|
||||
while(gpio_read(this->miso_pin_record))
|
||||
;
|
||||
last_status = SpiTransfer(CC1101_SRES);
|
||||
while(gpio_read(this->miso_pin_record))
|
||||
;
|
||||
gpio_write(ss_pin, true);
|
||||
}
|
||||
|
||||
bool CC1101::SpiSetRegValue(uint8_t reg, uint8_t value, uint8_t msb, uint8_t lsb) {
|
||||
if((msb > 7) || (lsb > 7) || (lsb > msb)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t current_value = SpiReadReg(reg);
|
||||
uint8_t mask = ~((0b11111111 << (msb + 1)) | (0b11111111 >> (8 - lsb)));
|
||||
uint8_t new_value = (current_value & ~mask) | (value & mask);
|
||||
SpiWriteReg(reg, new_value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
*FUNCTION NAME:Init
|
||||
*FUNCTION :CC1101 initialization
|
||||
*INPUT :none
|
||||
*OUTPUT :none
|
||||
****************************************************************/
|
||||
uint8_t CC1101::Init(void) {
|
||||
#ifdef CC1101_DEBUG
|
||||
printf("Init SPI...\r\n");
|
||||
#endif
|
||||
SpiInit(); //spi initialization
|
||||
gpio_write(ss_pin, true);
|
||||
// gpio_write(SCK_PIN, true);
|
||||
// gpio_write(MOSI_PIN, false);
|
||||
#ifdef CC1101_DEBUG
|
||||
printf("Reset CC1101...\r\n");
|
||||
#endif
|
||||
Reset(); // CC1101 reset
|
||||
|
||||
osDelay(150);
|
||||
|
||||
uint8_t partnum __attribute__((unused));
|
||||
uint8_t 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!\r\n");
|
||||
#endif
|
||||
|
||||
return version;
|
||||
}
|
||||
/****************************************************************
|
||||
*FUNCTION NAME:SetMod
|
||||
*FUNCTION :CC1101 modulation type
|
||||
*INPUT :byte mode
|
||||
*OUTPUT :none
|
||||
****************************************************************/
|
||||
void CC1101::SetMod(uint8_t 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)
|
||||
uint8_t 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)
|
||||
uint8_t 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("\r\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 Enable;variable length packets, packet length configured by the first byte after sync word
|
||||
SpiWriteReg(
|
||||
CC1101_PKTCTRL0, 0x33); //whitening off; asynchronous serial mode; CRC diable;reserved
|
||||
//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(uint8_t freq2, uint8_t freq1, uint8_t 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, (uint8_t)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\r\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;
|
||||
|
||||
bool CC1101::setRxBandwidth(float bandwidth) {
|
||||
if(bandwidth < 58.0 || bandwidth > 821.0) return false;
|
||||
|
||||
// set mode to standby
|
||||
SpiStrobe(CC1101_SIDLE);
|
||||
|
||||
// calculate exponent and mantissa values
|
||||
for(int8_t e = 3; e >= 0; e--) {
|
||||
for(int8_t m = 3; m >= 0; m--) {
|
||||
float point = (F_OSC) / (8 * (m + 4) * ((uint32_t)1 << e));
|
||||
if(fabs((bandwidth * 1000.0) - point) <= 1000) {
|
||||
// set Rx channel filter bandwidth
|
||||
SpiSetRegValue(CC1101_MDMCFG4, (e << 6) | (m << 4), 7, 4);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void getExpMant(
|
||||
float target,
|
||||
uint16_t mantOffset,
|
||||
uint8_t divExp,
|
||||
uint8_t expMax,
|
||||
uint8_t& exp,
|
||||
uint8_t& mant) {
|
||||
// get table origin point (exp = 0, mant = 0)
|
||||
float origin = (mantOffset * F_OSC) / ((uint32_t)1 << divExp);
|
||||
|
||||
// iterate over possible exponent values
|
||||
for(int8_t e = expMax; e >= 0; e--) {
|
||||
// get table column start value (exp = e, mant = 0);
|
||||
float intervalStart = ((uint32_t)1 << e) * origin;
|
||||
|
||||
// check if target value is in this column
|
||||
if(target >= intervalStart) {
|
||||
// save exponent value
|
||||
exp = e;
|
||||
|
||||
// calculate size of step between table rows
|
||||
float stepSize = intervalStart / (float)mantOffset;
|
||||
|
||||
// get target point position (exp = e, mant = m)
|
||||
mant = ((target - intervalStart) / stepSize);
|
||||
|
||||
// we only need the first match, terminate
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CC1101::setBitRate(float bitrate) {
|
||||
if(bitrate < 0.6 || bitrate > 500.0) return false;
|
||||
|
||||
// set mode to standby
|
||||
SpiStrobe(CC1101_SIDLE);
|
||||
|
||||
// calculate exponent and mantissa values
|
||||
uint8_t e = 0;
|
||||
uint8_t m = 0;
|
||||
getExpMant(bitrate * 1000.0, 256, 28, 14, e, m);
|
||||
|
||||
// set bit rate value
|
||||
SpiSetRegValue(CC1101_MDMCFG4, e, 3, 0);
|
||||
SpiSetRegValue(CC1101_MDMCFG3, m, 7, 0);
|
||||
|
||||
return true;
|
||||
}
|
@ -1,174 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#define F_OSC 26e6
|
||||
|
||||
/*******************************debug mode*************************************/
|
||||
// #define CC1101_DEBUG 1
|
||||
|
||||
//******************************CC1101 defines ********************************
|
||||
//******************************config registers *****************************
|
||||
#define CC1101_IOCFG2 0x00 //GDO2 output pin configration
|
||||
#define CC1101_IOCFG1 0x01 // GDO1 output pin configuration
|
||||
#define CC1101_IOCFG0 0x02 // GDO0 output pin configuration
|
||||
#define CC1101_FIFOTHR 0x03 // RX FIFO and TX FIFO thresholds
|
||||
#define CC1101_SYNC1 0x04 // Sync word, high INT8U
|
||||
#define CC1101_SYNC0 0x05 // Sync word, low INT8U
|
||||
#define CC1101_PKTLEN 0x06 // Packet length
|
||||
#define CC1101_PKTCTRL1 0x07 // Packet automation control
|
||||
#define CC1101_PKTCTRL0 0x08 // Packet automation control
|
||||
#define CC1101_ADDR 0x09 // Device address
|
||||
#define CC1101_CHANNR 0x0A // Channel number
|
||||
#define CC1101_FSCTRL1 0x0B // Frequency synthesizer control
|
||||
#define CC1101_FSCTRL0 0x0C // Frequency synthesizer control
|
||||
#define CC1101_FREQ2 0x0D // Frequency control word, high INT8U
|
||||
#define CC1101_FREQ1 0x0E // Frequency control word, middle INT8U
|
||||
#define CC1101_FREQ0 0x0F // Frequency control word, low INT8U
|
||||
#define CC1101_MDMCFG4 0x10 // Modem configuration
|
||||
#define CC1101_MDMCFG3 0x11 // Modem configuration
|
||||
#define CC1101_MDMCFG2 0x12 // Modem configuration
|
||||
#define CC1101_MDMCFG1 0x13 // Modem configuration
|
||||
#define CC1101_MDMCFG0 0x14 // Modem configuration
|
||||
#define CC1101_DEVIATN 0x15 // Modem deviation setting
|
||||
#define CC1101_MCSM2 0x16 // Main Radio Control State Machine configuration
|
||||
#define CC1101_MCSM1 0x17 // Main Radio Control State Machine configuration
|
||||
#define CC1101_MCSM0 0x18 // Main Radio Control State Machine configuration
|
||||
#define CC1101_FOCCFG 0x19 // Frequency Offset Compensation configuration
|
||||
#define CC1101_BSCFG 0x1A // Bit Synchronization configuration
|
||||
#define CC1101_AGCCTRL2 0x1B // AGC control
|
||||
#define CC1101_AGCCTRL1 0x1C // AGC control
|
||||
#define CC1101_AGCCTRL0 0x1D // AGC control
|
||||
#define CC1101_WOREVT1 0x1E // High INT8U Event 0 timeout
|
||||
#define CC1101_WOREVT0 0x1F // Low INT8U Event 0 timeout
|
||||
#define CC1101_WORCTRL 0x20 // Wake On Radio control
|
||||
#define CC1101_FREND1 0x21 // Front end RX configuration
|
||||
#define CC1101_FREND0 0x22 // Front end TX configuration
|
||||
#define CC1101_FSCAL3 0x23 // Frequency synthesizer calibration
|
||||
#define CC1101_FSCAL2 0x24 // Frequency synthesizer calibration
|
||||
#define CC1101_FSCAL1 0x25 // Frequency synthesizer calibration
|
||||
#define CC1101_FSCAL0 0x26 // Frequency synthesizer calibration
|
||||
#define CC1101_RCCTRL1 0x27 // RC oscillator configuration
|
||||
#define CC1101_RCCTRL0 0x28 // RC oscillator configuration
|
||||
#define CC1101_FSTEST 0x29 // Frequency synthesizer calibration control
|
||||
#define CC1101_PTEST 0x2A // Production test
|
||||
#define CC1101_AGCTEST 0x2B // AGC test
|
||||
#define CC1101_TEST2 0x2C // Various test settings
|
||||
#define CC1101_TEST1 0x2D // Various test settings
|
||||
#define CC1101_TEST0 0x2E // Various test settings
|
||||
|
||||
//*********************CC1101 Strobe commands *********************************
|
||||
#define CC1101_SRES 0x30 // Reset chip.
|
||||
|
||||
// Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1).
|
||||
// If in RX/TX: Go to a wait state where only the synthesizer is
|
||||
// running (for quick RX / TX turnaround).
|
||||
#define CC1101_SFSTXON 0x31
|
||||
|
||||
#define CC1101_SXOFF 0x32 // Turn off crystal oscillator.
|
||||
|
||||
// Calibrate frequency synthesizer and turn it off
|
||||
// (enables quick start).
|
||||
#define CC1101_SCAL 0x33
|
||||
|
||||
// Enable RX. Perform calibration first if coming from IDLE and
|
||||
// MCSM0.FS_AUTOCAL=1.
|
||||
#define CC1101_SRX 0x34
|
||||
|
||||
// In IDLE state: Enable TX. Perform calibration first if
|
||||
// MCSM0.FS_AUTOCAL=1. If in RX state and CCA is enabled:
|
||||
// Only go to TX if channel is clear.
|
||||
#define CC1101_STX 0x35
|
||||
|
||||
// Exit RX / TX, turn off frequency synthesizer and exit
|
||||
// Wake-On-Radio mode if applicable.
|
||||
#define CC1101_SIDLE 0x36
|
||||
|
||||
#define CC1101_SAFC 0x37 // Perform AFC adjustment of the frequency synthesizer
|
||||
#define CC1101_SWOR 0x38 // Start automatic RX polling sequence (Wake-on-Radio)
|
||||
#define CC1101_SPWD 0x39 // Enter power down mode when CSn goes high.
|
||||
#define CC1101_SFRX 0x3A // Flush the RX FIFO buffer.
|
||||
#define CC1101_SFTX 0x3B // Flush the TX FIFO buffer.
|
||||
#define CC1101_SWORRST 0x3C // Reset real time clock.
|
||||
|
||||
// No operation. May be used to pad strobe commands to two
|
||||
// INT8Us for simpler software.
|
||||
#define CC1101_SNOP 0x3D
|
||||
|
||||
//**************************CC1101 STATUS REGSITER ****************************
|
||||
//use burst read to access
|
||||
#define CC1101_PARTNUM 0x30
|
||||
#define CC1101_VERSION 0x31
|
||||
#define CC1101_FREQEST 0x32
|
||||
#define CC1101_LQI 0x33
|
||||
#define CC1101_RSSI 0x34
|
||||
#define CC1101_MARCSTATE 0x35
|
||||
#define CC1101_WORTIME1 0x36
|
||||
#define CC1101_WORTIME0 0x37
|
||||
#define CC1101_PKTSTATUS 0x38
|
||||
#define CC1101_VCO_VC_DAC 0x39
|
||||
#define CC1101_TXBYTES 0x3A
|
||||
#define CC1101_RXBYTES 0x3B
|
||||
#define CC1101_RCCTRL1_STATUS 0x3C
|
||||
#define CC1101_RCCTRL_STATUS 0x3D
|
||||
/****************************cc1101 status ***********************************/
|
||||
#define CC1101_STATUS_RX 0x0D
|
||||
#define CC1101_STATUS_TX 0x13
|
||||
|
||||
//***********************CC1101 PATABLE,TXFIFO,RXFIFO**************************
|
||||
#define CC1101_PATABLE 0x3E
|
||||
#define CC1101_TXFIFO 0x3F
|
||||
#define CC1101_RXFIFO 0x3F
|
||||
|
||||
//******************************* pins ****************************************
|
||||
// #define SCK_PIN 13
|
||||
// #define MISO_PIN 12
|
||||
// #define MOSI_PIN 11
|
||||
// #define SS_PIN 10
|
||||
// #define GDO0 8 //pin assignment
|
||||
// #define GDO2 9
|
||||
//*****************************CC1101 Config**********************************
|
||||
//no pa ramping, output power to 10dBm
|
||||
#define POWER 0xC0 //output power to maximum
|
||||
//modulation
|
||||
#define FSK2 0x00
|
||||
#define GFSK 0x10
|
||||
#define ASK 0x30
|
||||
#define FSK4 0x40
|
||||
#define MSK 0x70
|
||||
//******************************** class **************************************//
|
||||
class CC1101 {
|
||||
private:
|
||||
GpioPin* ss_pin;
|
||||
GpioPin miso_pin;
|
||||
GpioPin* miso_pin_record;
|
||||
GpioPin* gdo0_pin;
|
||||
GpioPin* gdo2_pin;
|
||||
|
||||
private:
|
||||
void SpiMode(uint8_t config);
|
||||
uint8_t SpiTransfer(uint8_t value);
|
||||
void Reset(void);
|
||||
void SpiWriteBurstReg(uint8_t addr, uint8_t* buffer, uint8_t num);
|
||||
uint8_t SpiReadReg(uint8_t addr);
|
||||
void RegConfigSettings(void);
|
||||
|
||||
public:
|
||||
CC1101(GpioPin* ss_pin);
|
||||
|
||||
void SpiWriteReg(uint8_t addr, uint8_t value);
|
||||
bool SpiSetRegValue(uint8_t reg, uint8_t value, uint8_t msb, uint8_t lsb);
|
||||
void SpiReadBurstReg(uint8_t addr, uint8_t* buffer, uint8_t num);
|
||||
void SpiInit(void);
|
||||
void SpiEnd(void);
|
||||
void SetMod(uint8_t mode);
|
||||
void SetFreq(uint8_t Freq2, uint8_t Freq1, uint8_t Freq0);
|
||||
uint8_t Init(void);
|
||||
void SpiStrobe(uint8_t strobe);
|
||||
uint8_t SpiReadStatus(uint8_t addr);
|
||||
void SetReceive(void);
|
||||
void SetTransmit(void);
|
||||
void SetChannel(int channel);
|
||||
bool setRxBandwidth(float bandwidth);
|
||||
bool setBitRate(float bitrate);
|
||||
};
|
@ -34,6 +34,7 @@ void canvas_free(Canvas* canvas) {
|
||||
|
||||
void canvas_reset(Canvas* canvas) {
|
||||
furi_assert(canvas);
|
||||
canvas_clear(canvas);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
}
|
||||
|
@ -1,122 +1,66 @@
|
||||
#include "u8g2/u8g2.h"
|
||||
#include <furi.h>
|
||||
#include <api-hal.h>
|
||||
#include <furi.h>
|
||||
|
||||
#include <main.h>
|
||||
|
||||
extern SPI_HandleTypeDef SPI_D;
|
||||
|
||||
// TODO: fix log
|
||||
#ifdef DEBUG
|
||||
#undef DEBUG
|
||||
#endif
|
||||
static ApiHalSpiDevice* u8g2_periphery_display = NULL;
|
||||
|
||||
uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr) {
|
||||
switch(msg) {
|
||||
//Initialize SPI peripheral
|
||||
case U8X8_MSG_GPIO_AND_DELAY_INIT:
|
||||
/* HAL initialization contains all what we need so we can skip this part. */
|
||||
break;
|
||||
|
||||
//Function which implements a delay, arg_int contains the amount of ms
|
||||
case U8X8_MSG_DELAY_MILLI:
|
||||
osDelay(arg_int);
|
||||
break;
|
||||
|
||||
//Function which delays 10us
|
||||
case U8X8_MSG_DELAY_10MICRO:
|
||||
delay_us(10);
|
||||
break;
|
||||
|
||||
//Function which delays 100ns
|
||||
case U8X8_MSG_DELAY_100NANO:
|
||||
asm("nop");
|
||||
break;
|
||||
|
||||
// Function to define the logic level of the RESET line
|
||||
case U8X8_MSG_GPIO_RESET:
|
||||
#ifdef DEBUG
|
||||
printf("[u8g2] rst %d\n", arg_int);
|
||||
#endif
|
||||
|
||||
// TODO change it to FuriRecord pin
|
||||
HAL_GPIO_WritePin(
|
||||
DISPLAY_RST_GPIO_Port, DISPLAY_RST_Pin, arg_int ? GPIO_PIN_SET : GPIO_PIN_RESET);
|
||||
hal_gpio_write(&gpio_display_rst, arg_int);
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr) {
|
||||
switch(msg) {
|
||||
case U8X8_MSG_BYTE_SEND:
|
||||
api_hal_spi_bus_tx(u8g2_periphery_display->bus, (uint8_t*)arg_ptr, arg_int, 10000);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_BYTE_SET_DC:
|
||||
hal_gpio_write(&gpio_display_di, arg_int);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_BYTE_INIT:
|
||||
break;
|
||||
|
||||
case U8X8_MSG_BYTE_START_TRANSFER:
|
||||
furi_assert(u8g2_periphery_display == NULL);
|
||||
u8g2_periphery_display =
|
||||
(ApiHalSpiDevice*)api_hal_spi_device_get(ApiHalSpiDeviceIdDisplay);
|
||||
hal_gpio_write(u8g2_periphery_display->chip_select, false);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_BYTE_END_TRANSFER:
|
||||
furi_assert(u8g2_periphery_display);
|
||||
hal_gpio_write(u8g2_periphery_display->chip_select, true);
|
||||
api_hal_spi_device_return(u8g2_periphery_display);
|
||||
u8g2_periphery_display = NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
printf("[u8g2] unknown io %d\n", msg);
|
||||
#endif
|
||||
|
||||
return 0; //A message was received which is not implemented, return 0 to indicate an error
|
||||
}
|
||||
|
||||
return 1; // command processed successfully.
|
||||
}
|
||||
|
||||
uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr) {
|
||||
switch(msg) {
|
||||
case U8X8_MSG_BYTE_SEND:
|
||||
#ifdef DEBUG
|
||||
printf("[u8g2] send %d bytes %02X\n", arg_int, ((uint8_t*)arg_ptr)[0]);
|
||||
#endif
|
||||
|
||||
// TODO change it to FuriRecord SPI
|
||||
HAL_SPI_Transmit(&SPI_D, (uint8_t*)arg_ptr, arg_int, 10000);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_BYTE_SET_DC:
|
||||
#ifdef DEBUG
|
||||
printf("[u8g2] dc %d\n", arg_int);
|
||||
#endif
|
||||
|
||||
// TODO change it to FuriRecord pin
|
||||
HAL_GPIO_WritePin(
|
||||
DISPLAY_DI_GPIO_Port, DISPLAY_DI_Pin, arg_int ? GPIO_PIN_SET : GPIO_PIN_RESET);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_BYTE_INIT:
|
||||
#ifdef DEBUG
|
||||
printf("[u8g2] init\r\n");
|
||||
#endif
|
||||
|
||||
// TODO change it to FuriRecord pin
|
||||
HAL_GPIO_WritePin(DISPLAY_CS_GPIO_Port, DISPLAY_CS_Pin, GPIO_PIN_RESET);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_BYTE_START_TRANSFER:
|
||||
#ifdef DEBUG
|
||||
printf("[u8g2] start\r\n");
|
||||
#endif
|
||||
|
||||
// TODO: SPI manager
|
||||
api_hal_spi_lock_device(&display_spi);
|
||||
|
||||
// TODO change it to FuriRecord pin
|
||||
HAL_GPIO_WritePin(DISPLAY_CS_GPIO_Port, DISPLAY_CS_Pin, GPIO_PIN_RESET);
|
||||
asm("nop");
|
||||
break;
|
||||
|
||||
case U8X8_MSG_BYTE_END_TRANSFER:
|
||||
#ifdef DEBUG
|
||||
printf("[u8g2] end\r\n");
|
||||
#endif
|
||||
|
||||
asm("nop");
|
||||
// TODO change it to FuriRecord pin
|
||||
HAL_GPIO_WritePin(DISPLAY_CS_GPIO_Port, DISPLAY_CS_Pin, GPIO_PIN_SET);
|
||||
|
||||
// TODO: SPI manager
|
||||
api_hal_spi_unlock_device(&display_spi);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
#ifdef DEBUG
|
||||
printf("[u8g2] unknown xfer %d\n", msg);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -37,12 +37,12 @@ static void render_callback(Canvas* canvas, void* ctx) {
|
||||
|
||||
canvas_draw_str(canvas, 2, 24, state->on ? "Reading" : "Emulating");
|
||||
|
||||
char buf[14];
|
||||
char buf[30];
|
||||
|
||||
sprintf(buf, "%d kHz", (int)state->freq_khz);
|
||||
snprintf(buf, sizeof(buf), "%d kHz", (int)state->freq_khz);
|
||||
canvas_draw_str(canvas, 2, 36, buf);
|
||||
|
||||
sprintf(buf, "%02d:%010ld", state->customer_id, state->em_data);
|
||||
snprintf(buf, sizeof(buf), "%02d:%010ld", state->customer_id, state->em_data);
|
||||
canvas_draw_str(canvas, 2, 45, buf);
|
||||
|
||||
release_mutex((ValueMutex*)ctx, state);
|
||||
|
@ -244,7 +244,7 @@ ReturnCode nfc_worker_trx(
|
||||
}
|
||||
|
||||
void nfc_worker_exchange(NfcWorker* nfc_worker, rfalNfcDevice* nfc_device) {
|
||||
ReturnCode err;
|
||||
ReturnCode err = ERR_NONE;
|
||||
uint8_t* rxData;
|
||||
uint16_t* rcvLen;
|
||||
uint8_t txBuf[100];
|
||||
|
@ -849,4 +849,4 @@ int32_t sd_filesystem(void* p) {
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
#include "../subghz-event.h"
|
||||
|
||||
class SubghzApp;
|
||||
|
||||
class SubghzScene {
|
||||
public:
|
||||
virtual void on_enter(SubghzApp* app) = 0;
|
||||
virtual bool on_event(SubghzApp* app, SubghzEvent* event) = 0;
|
||||
virtual void on_exit(SubghzApp* app) = 0;
|
||||
|
||||
private:
|
||||
};
|
@ -1,48 +0,0 @@
|
||||
#include "subghz-scene-spectrum-settings.h"
|
||||
#include "../subghz-app.h"
|
||||
#include "../subghz-view-manager.h"
|
||||
#include "../subghz-event.h"
|
||||
#include <callback-connector.h>
|
||||
|
||||
void SubghzSceneSpectrumSettings::on_enter(SubghzApp* app) {
|
||||
SubghzAppViewManager* view_manager = app->get_view_manager();
|
||||
SubghzViewSpectrumSettings* spectrum_settings = view_manager->get_spectrum_settings();
|
||||
|
||||
auto callback = cbc::obtain_connector(this, &SubghzSceneSpectrumSettings::ok_callback);
|
||||
spectrum_settings->set_ok_callback(callback, app);
|
||||
spectrum_settings->set_start_freq(433);
|
||||
|
||||
view_manager->switch_to(SubghzAppViewManager::ViewType::SpectrumSettings);
|
||||
}
|
||||
|
||||
bool SubghzSceneSpectrumSettings::on_event(SubghzApp* app, SubghzEvent* event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == SubghzEvent::Type::NextScene) {
|
||||
// save data
|
||||
// uint32_t start_freq = app->get_view_manager()->get_spectrum_settings()->get_start_freq();
|
||||
// app->get_spectrum_analyzer()->set_start_freq(start_freq);
|
||||
|
||||
// switch to next scene
|
||||
// app->switch_to_next_scene(SubghzApp::Scene::SceneSpectrumAnalyze);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void SubghzSceneSpectrumSettings::on_exit(SubghzApp* app) {
|
||||
SubghzAppViewManager* view_manager = app->get_view_manager();
|
||||
SubghzViewSpectrumSettings* spectrum_settings = view_manager->get_spectrum_settings();
|
||||
|
||||
spectrum_settings->set_ok_callback(nullptr, nullptr);
|
||||
spectrum_settings->set_start_freq(0);
|
||||
}
|
||||
|
||||
void SubghzSceneSpectrumSettings::ok_callback(void* context) {
|
||||
SubghzApp* app = static_cast<SubghzApp*>(context);
|
||||
SubghzEvent event;
|
||||
|
||||
event.type = SubghzEvent::Type::NextScene;
|
||||
app->get_view_manager()->send_event(&event);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
#pragma once
|
||||
#include "subghz-scene-generic.h"
|
||||
|
||||
class SubghzSceneSpectrumSettings : public SubghzScene {
|
||||
public:
|
||||
void on_enter(SubghzApp* app) final;
|
||||
bool on_event(SubghzApp* app, SubghzEvent* event) final;
|
||||
void on_exit(SubghzApp* app) final;
|
||||
|
||||
private:
|
||||
void ok_callback(void* context);
|
||||
};
|
@ -1,67 +0,0 @@
|
||||
#include "subghz-scene-start.h"
|
||||
#include "../subghz-app.h"
|
||||
#include "../subghz-view-manager.h"
|
||||
#include "../subghz-event.h"
|
||||
#include <callback-connector.h>
|
||||
|
||||
typedef enum {
|
||||
SubmenuIndexSpectrumAnalyzer,
|
||||
SubmenuIndexFrequencyScanner,
|
||||
SubmenuIndexSignalAnalyzer,
|
||||
SubmenuIndexSignalTransmitter,
|
||||
SubmenuIndexApplications,
|
||||
} SubmenuIndex;
|
||||
|
||||
void SubghzSceneStart::on_enter(SubghzApp* app) {
|
||||
SubghzAppViewManager* view_manager = app->get_view_manager();
|
||||
Submenu* submenu = view_manager->get_submenu();
|
||||
auto callback = cbc::obtain_connector(this, &SubghzSceneStart::submenu_callback);
|
||||
|
||||
submenu_add_item(submenu, "Spectrum Analyzer", SubmenuIndexSpectrumAnalyzer, callback, app);
|
||||
submenu_add_item(submenu, "Frequency Scanner", SubmenuIndexFrequencyScanner, callback, app);
|
||||
submenu_add_item(submenu, "Signal Analyzer", SubmenuIndexSignalAnalyzer, callback, app);
|
||||
submenu_add_item(submenu, "Signal Transmitter", SubmenuIndexSignalTransmitter, callback, app);
|
||||
submenu_add_item(submenu, "Applications", SubmenuIndexApplications, callback, app);
|
||||
|
||||
view_manager->switch_to(SubghzAppViewManager::ViewType::Submenu);
|
||||
}
|
||||
|
||||
bool SubghzSceneStart::on_event(SubghzApp* app, SubghzEvent* event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == SubghzEvent::Type::MenuSelected) {
|
||||
switch(event->payload.menu_index) {
|
||||
case SubmenuIndexSpectrumAnalyzer:
|
||||
app->switch_to_next_scene(SubghzApp::Scene::SceneSpectrumSettings);
|
||||
break;
|
||||
case SubmenuIndexFrequencyScanner:
|
||||
break;
|
||||
case SubmenuIndexSignalAnalyzer:
|
||||
break;
|
||||
case SubmenuIndexSignalTransmitter:
|
||||
break;
|
||||
case SubmenuIndexApplications:
|
||||
break;
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void SubghzSceneStart::on_exit(SubghzApp* app) {
|
||||
SubghzAppViewManager* view_manager = app->get_view_manager();
|
||||
Submenu* submenu = view_manager->get_submenu();
|
||||
|
||||
submenu_clean(submenu);
|
||||
}
|
||||
|
||||
void SubghzSceneStart::submenu_callback(void* context, uint32_t index) {
|
||||
SubghzApp* app = static_cast<SubghzApp*>(context);
|
||||
SubghzEvent event;
|
||||
|
||||
event.type = SubghzEvent::Type::MenuSelected;
|
||||
event.payload.menu_index = index;
|
||||
|
||||
app->get_view_manager()->send_event(&event);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
#pragma once
|
||||
#include "subghz-scene-generic.h"
|
||||
|
||||
class SubghzSceneStart : public SubghzScene {
|
||||
public:
|
||||
void on_enter(SubghzApp* app) final;
|
||||
bool on_event(SubghzApp* app, SubghzEvent* event) final;
|
||||
void on_exit(SubghzApp* app) final;
|
||||
|
||||
private:
|
||||
void submenu_callback(void* context, uint32_t index);
|
||||
};
|
@ -1,90 +0,0 @@
|
||||
#include "subghz-app.h"
|
||||
#include <api-hal-power.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
void SubghzApp::run(void) {
|
||||
SubghzEvent event;
|
||||
bool consumed;
|
||||
bool exit = false;
|
||||
|
||||
scenes[current_scene]->on_enter(this);
|
||||
|
||||
while(!exit) {
|
||||
view.receive_event(&event);
|
||||
|
||||
consumed = scenes[current_scene]->on_event(this, &event);
|
||||
|
||||
if(!consumed) {
|
||||
if(event.type == SubghzEvent::Type::Back) {
|
||||
exit = switch_to_previous_scene();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
scenes[current_scene]->on_exit(this);
|
||||
}
|
||||
|
||||
SubghzApp::SubghzApp() {
|
||||
api_hal_power_insomnia_enter();
|
||||
}
|
||||
|
||||
SubghzApp::~SubghzApp() {
|
||||
api_hal_power_insomnia_exit();
|
||||
}
|
||||
|
||||
SubghzAppViewManager* SubghzApp::get_view_manager() {
|
||||
return &view;
|
||||
}
|
||||
|
||||
void SubghzApp::switch_to_next_scene(Scene next_scene) {
|
||||
previous_scenes_list.push_front(current_scene);
|
||||
|
||||
if(next_scene != Scene::SceneExit) {
|
||||
scenes[current_scene]->on_exit(this);
|
||||
current_scene = next_scene;
|
||||
scenes[current_scene]->on_enter(this);
|
||||
}
|
||||
}
|
||||
|
||||
void SubghzApp::search_and_switch_to_previous_scene(std::initializer_list<Scene> scenes_list) {
|
||||
Scene previous_scene = Scene::SceneStart;
|
||||
bool scene_found = false;
|
||||
|
||||
while(!scene_found) {
|
||||
previous_scene = get_previous_scene();
|
||||
for(Scene element : scenes_list) {
|
||||
if(previous_scene == element || previous_scene == Scene::SceneStart) {
|
||||
scene_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scenes[current_scene]->on_exit(this);
|
||||
current_scene = previous_scene;
|
||||
scenes[current_scene]->on_enter(this);
|
||||
}
|
||||
|
||||
bool SubghzApp::switch_to_previous_scene(uint8_t count) {
|
||||
Scene previous_scene = Scene::SceneStart;
|
||||
|
||||
for(uint8_t i = 0; i < count; i++) {
|
||||
previous_scene = get_previous_scene();
|
||||
if(previous_scene == Scene::SceneExit) break;
|
||||
}
|
||||
|
||||
if(previous_scene == Scene::SceneExit) {
|
||||
return true;
|
||||
} else {
|
||||
scenes[current_scene]->on_exit(this);
|
||||
current_scene = previous_scene;
|
||||
scenes[current_scene]->on_enter(this);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SubghzApp::Scene SubghzApp::get_previous_scene() {
|
||||
Scene scene = previous_scenes_list.front();
|
||||
previous_scenes_list.pop_front();
|
||||
return scene;
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include "subghz-view-manager.h"
|
||||
|
||||
#include "scene/subghz-scene-start.h"
|
||||
#include "scene/subghz-scene-spectrum-settings.h"
|
||||
|
||||
class SubghzApp {
|
||||
public:
|
||||
void run(void);
|
||||
|
||||
SubghzApp();
|
||||
~SubghzApp();
|
||||
|
||||
enum class Scene : uint8_t {
|
||||
SceneExit,
|
||||
SceneStart,
|
||||
SceneSpectrumSettings,
|
||||
};
|
||||
|
||||
SubghzAppViewManager* get_view_manager();
|
||||
void switch_to_next_scene(Scene index);
|
||||
void search_and_switch_to_previous_scene(std::initializer_list<Scene> scenes_list);
|
||||
bool switch_to_previous_scene(uint8_t count = 1);
|
||||
Scene get_previous_scene();
|
||||
|
||||
private:
|
||||
std::list<Scene> previous_scenes_list = {Scene::SceneExit};
|
||||
Scene current_scene = Scene::SceneStart;
|
||||
SubghzAppViewManager view;
|
||||
|
||||
std::map<Scene, SubghzScene*> scenes = {
|
||||
{Scene::SceneStart, new SubghzSceneStart()},
|
||||
{Scene::SceneSpectrumSettings, new SubghzSceneSpectrumSettings()},
|
||||
};
|
||||
};
|
@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
class SubghzEvent {
|
||||
public:
|
||||
// events enum
|
||||
enum class Type : uint8_t {
|
||||
Tick,
|
||||
Back,
|
||||
MenuSelected,
|
||||
NextScene,
|
||||
};
|
||||
|
||||
// payload
|
||||
union {
|
||||
uint32_t menu_index;
|
||||
} payload;
|
||||
|
||||
// event type
|
||||
Type type;
|
||||
};
|
@ -1,81 +0,0 @@
|
||||
#include "subghz-view-manager.h"
|
||||
#include "subghz-event.h"
|
||||
#include <callback-connector.h>
|
||||
|
||||
SubghzAppViewManager::SubghzAppViewManager() {
|
||||
event_queue = osMessageQueueNew(10, sizeof(SubghzEvent), NULL);
|
||||
|
||||
view_dispatcher = view_dispatcher_alloc();
|
||||
auto callback = cbc::obtain_connector(this, &SubghzAppViewManager::previous_view_callback);
|
||||
|
||||
// allocate views
|
||||
submenu = submenu_alloc();
|
||||
view_dispatcher_add_view(
|
||||
view_dispatcher,
|
||||
static_cast<uint32_t>(SubghzAppViewManager::ViewType::Submenu),
|
||||
submenu_get_view(submenu));
|
||||
|
||||
spectrum_settings = new SubghzViewSpectrumSettings();
|
||||
view_dispatcher_add_view(
|
||||
view_dispatcher,
|
||||
static_cast<uint32_t>(SubghzAppViewManager::ViewType::SpectrumSettings),
|
||||
spectrum_settings->get_view());
|
||||
|
||||
gui = static_cast<Gui*>(furi_record_open("gui"));
|
||||
view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
// set previous view callback for all views
|
||||
view_set_previous_callback(submenu_get_view(submenu), callback);
|
||||
view_set_previous_callback(spectrum_settings->get_view(), callback);
|
||||
}
|
||||
|
||||
SubghzAppViewManager::~SubghzAppViewManager() {
|
||||
// remove views
|
||||
view_dispatcher_remove_view(
|
||||
view_dispatcher, static_cast<uint32_t>(SubghzAppViewManager::ViewType::Submenu));
|
||||
view_dispatcher_remove_view(
|
||||
view_dispatcher, static_cast<uint32_t>(SubghzAppViewManager::ViewType::SpectrumSettings));
|
||||
|
||||
// free view modules
|
||||
submenu_free(submenu);
|
||||
free(spectrum_settings);
|
||||
|
||||
// free dispatcher
|
||||
view_dispatcher_free(view_dispatcher);
|
||||
|
||||
// free event queue
|
||||
osMessageQueueDelete(event_queue);
|
||||
}
|
||||
|
||||
void SubghzAppViewManager::switch_to(ViewType type) {
|
||||
view_dispatcher_switch_to_view(view_dispatcher, static_cast<uint32_t>(type));
|
||||
}
|
||||
|
||||
Submenu* SubghzAppViewManager::get_submenu() {
|
||||
return submenu;
|
||||
}
|
||||
|
||||
SubghzViewSpectrumSettings* SubghzAppViewManager::get_spectrum_settings() {
|
||||
return spectrum_settings;
|
||||
}
|
||||
|
||||
void SubghzAppViewManager::receive_event(SubghzEvent* event) {
|
||||
if(osMessageQueueGet(event_queue, event, NULL, 100) != osOK) {
|
||||
event->type = SubghzEvent::Type::Tick;
|
||||
}
|
||||
}
|
||||
|
||||
void SubghzAppViewManager::send_event(SubghzEvent* event) {
|
||||
osStatus_t result = osMessageQueuePut(event_queue, event, 0, 0);
|
||||
furi_check(result == osOK);
|
||||
}
|
||||
|
||||
uint32_t SubghzAppViewManager::previous_view_callback(void* context) {
|
||||
if(event_queue != NULL) {
|
||||
SubghzEvent event;
|
||||
event.type = SubghzEvent::Type::Back;
|
||||
send_event(&event);
|
||||
}
|
||||
|
||||
return VIEW_IGNORE;
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
#pragma once
|
||||
#include <furi.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
#include "subghz-event.h"
|
||||
#include "view/subghz-view-spectrum-settings.h"
|
||||
|
||||
class SubghzAppViewManager {
|
||||
public:
|
||||
enum class ViewType : uint8_t {
|
||||
Submenu,
|
||||
SpectrumSettings,
|
||||
};
|
||||
|
||||
osMessageQueueId_t event_queue;
|
||||
|
||||
SubghzAppViewManager();
|
||||
~SubghzAppViewManager();
|
||||
|
||||
void switch_to(ViewType type);
|
||||
|
||||
void receive_event(SubghzEvent* event);
|
||||
void send_event(SubghzEvent* event);
|
||||
|
||||
Submenu* get_submenu();
|
||||
SubghzViewSpectrumSettings* get_spectrum_settings();
|
||||
|
||||
private:
|
||||
ViewDispatcher* view_dispatcher;
|
||||
Gui* gui;
|
||||
|
||||
uint32_t previous_view_callback(void* context);
|
||||
|
||||
// view elements
|
||||
Submenu* submenu;
|
||||
SubghzViewSpectrumSettings* spectrum_settings;
|
||||
};
|
98
applications/subghz/subghz.c
Normal file
98
applications/subghz/subghz.c
Normal file
@ -0,0 +1,98 @@
|
||||
#include "subghz_i.h"
|
||||
|
||||
osThreadId subghz_thread_id = NULL;
|
||||
|
||||
void subghz_menu_callback(void* context, uint32_t index) {
|
||||
furi_assert(context);
|
||||
|
||||
SubGhz* subghz = context;
|
||||
|
||||
if(index == 0) {
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewTestBasic);
|
||||
} else if(index == 1) {
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewTestPacket);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t subghz_exit(void* context) {
|
||||
osThreadResume(subghz_thread_id);
|
||||
return VIEW_NONE;
|
||||
}
|
||||
|
||||
SubGhz* subghz_alloc() {
|
||||
SubGhz* subghz = furi_alloc(sizeof(SubGhz));
|
||||
|
||||
// Thread id
|
||||
subghz_thread_id = osThreadGetId();
|
||||
|
||||
// GUI
|
||||
subghz->gui = furi_record_open("gui");
|
||||
|
||||
// View Dispatcher
|
||||
subghz->view_dispatcher = view_dispatcher_alloc();
|
||||
view_dispatcher_attach_to_gui(
|
||||
subghz->view_dispatcher, subghz->gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
// Menu
|
||||
subghz->submenu = submenu_alloc();
|
||||
submenu_add_item(subghz->submenu, "Basic Test", 0, subghz_menu_callback, subghz);
|
||||
submenu_add_item(subghz->submenu, "Packet Test", 1, subghz_menu_callback, subghz);
|
||||
View* submenu_view = submenu_get_view(subghz->submenu);
|
||||
view_set_previous_callback(submenu_view, subghz_exit);
|
||||
view_dispatcher_add_view(subghz->view_dispatcher, SubGhzViewMenu, submenu_view);
|
||||
|
||||
// Basic Test Module
|
||||
subghz->subghz_test_basic = subghz_test_basic_alloc();
|
||||
view_dispatcher_add_view(
|
||||
subghz->view_dispatcher,
|
||||
SubGhzViewTestBasic,
|
||||
subghz_test_basic_get_view(subghz->subghz_test_basic));
|
||||
|
||||
// Packet Test
|
||||
subghz->subghz_test_packet = subghz_test_packet_alloc();
|
||||
view_dispatcher_add_view(
|
||||
subghz->view_dispatcher,
|
||||
SubGhzViewTestPacket,
|
||||
subghz_test_packet_get_view(subghz->subghz_test_packet));
|
||||
|
||||
// Switch to menu
|
||||
view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewMenu);
|
||||
|
||||
return subghz;
|
||||
}
|
||||
|
||||
void subghz_free(SubGhz* subghz) {
|
||||
furi_assert(subghz);
|
||||
|
||||
// Packet Test
|
||||
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewTestPacket);
|
||||
subghz_test_packet_free(subghz->subghz_test_packet);
|
||||
|
||||
// Basic Test
|
||||
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewTestBasic);
|
||||
subghz_test_basic_free(subghz->subghz_test_basic);
|
||||
|
||||
// Submenu
|
||||
view_dispatcher_remove_view(subghz->view_dispatcher, SubGhzViewMenu);
|
||||
submenu_free(subghz->submenu);
|
||||
|
||||
// View Dispatcher
|
||||
view_dispatcher_free(subghz->view_dispatcher);
|
||||
|
||||
// GUI
|
||||
furi_record_close("gui");
|
||||
subghz->gui = NULL;
|
||||
|
||||
// The rest
|
||||
free(subghz);
|
||||
}
|
||||
|
||||
int32_t subghz_app(void* context) {
|
||||
SubGhz* subghz = subghz_alloc();
|
||||
|
||||
osThreadSuspend(subghz_thread_id);
|
||||
|
||||
subghz_free(subghz);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
#include "subghz-app.h"
|
||||
|
||||
// app enter function
|
||||
extern "C" int32_t app_subghz(void* p) {
|
||||
SubghzApp* app = new SubghzApp();
|
||||
app->run();
|
||||
delete app;
|
||||
|
||||
return 255;
|
||||
}
|
3
applications/subghz/subghz.h
Normal file
3
applications/subghz/subghz.h
Normal file
@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
typedef struct SubGhz SubGhz;
|
44
applications/subghz/subghz_i.h
Normal file
44
applications/subghz/subghz_i.h
Normal file
@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include "subghz.h"
|
||||
#include "subghz_test_basic.h"
|
||||
#include "subghz_test_packet.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
|
||||
static const uint32_t subghz_frequencies[] = {
|
||||
301000000,
|
||||
315000000,
|
||||
346000000,
|
||||
385000000,
|
||||
433920000,
|
||||
438900000,
|
||||
463000000,
|
||||
781000000,
|
||||
868000000,
|
||||
915000000,
|
||||
925000000,
|
||||
};
|
||||
|
||||
static const uint32_t subghz_frequencies_count = sizeof(subghz_frequencies) / sizeof(uint32_t);
|
||||
|
||||
struct SubGhz {
|
||||
Gui* gui;
|
||||
|
||||
ViewDispatcher* view_dispatcher;
|
||||
|
||||
Submenu* submenu;
|
||||
|
||||
SubghzTestBasic* subghz_test_basic;
|
||||
|
||||
SubghzTestPacket* subghz_test_packet;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
SubGhzViewMenu,
|
||||
SubGhzViewTestBasic,
|
||||
SubGhzViewTestPacket,
|
||||
} SubGhzView;
|
203
applications/subghz/subghz_test_basic.c
Normal file
203
applications/subghz/subghz_test_basic.c
Normal file
@ -0,0 +1,203 @@
|
||||
#include "subghz_test_basic.h"
|
||||
#include "subghz_i.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <furi.h>
|
||||
#include <api-hal.h>
|
||||
#include <input/input.h>
|
||||
|
||||
struct SubghzTestBasic {
|
||||
View* view;
|
||||
osTimerId timer;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
SubghzTestBasicModelStatusRx,
|
||||
SubghzTestBasicModelStatusTx,
|
||||
} SubghzTestBasicModelStatus;
|
||||
|
||||
typedef struct {
|
||||
uint8_t frequency;
|
||||
uint32_t real_frequency;
|
||||
ApiHalSubGhzPath path;
|
||||
float rssi;
|
||||
SubghzTestBasicModelStatus status;
|
||||
} SubghzTestBasicModel;
|
||||
|
||||
void subghz_test_basic_draw(Canvas* canvas, SubghzTestBasicModel* model) {
|
||||
char buffer[64];
|
||||
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str(canvas, 2, 12, "CC1101 Basic Test");
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
// Frequency
|
||||
snprintf(
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
"Freq: %03ld.%03ld.%03ld Hz",
|
||||
model->real_frequency / 1000000 % 1000,
|
||||
model->real_frequency / 1000 % 1000,
|
||||
model->real_frequency % 1000);
|
||||
canvas_draw_str(canvas, 2, 24, buffer);
|
||||
// Path
|
||||
char* path_name = "Unknown";
|
||||
if(model->path == ApiHalSubGhzPathIsolate) {
|
||||
path_name = "isolate";
|
||||
} else if(model->path == ApiHalSubGhzPath1) {
|
||||
path_name = "433MHz";
|
||||
} else if(model->path == ApiHalSubGhzPath2) {
|
||||
path_name = "315MHz";
|
||||
} else if(model->path == ApiHalSubGhzPath3) {
|
||||
path_name = "868MHz";
|
||||
}
|
||||
snprintf(buffer, sizeof(buffer), "Path: %d - %s", model->path, path_name);
|
||||
canvas_draw_str(canvas, 2, 36, buffer);
|
||||
if(model->status == SubghzTestBasicModelStatusRx) {
|
||||
snprintf(
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
"RSSI: %ld.%ld dBm",
|
||||
(int32_t)(model->rssi),
|
||||
(int32_t)fabs(model->rssi * 10) % 10);
|
||||
canvas_draw_str(canvas, 2, 48, buffer);
|
||||
} else {
|
||||
canvas_draw_str(canvas, 2, 48, "TX");
|
||||
}
|
||||
}
|
||||
|
||||
bool subghz_test_basic_input(InputEvent* event, void* context) {
|
||||
furi_assert(context);
|
||||
SubghzTestBasic* subghz_test_basic = context;
|
||||
|
||||
if(event->key == InputKeyBack) {
|
||||
return false;
|
||||
}
|
||||
|
||||
with_view_model(
|
||||
subghz_test_basic->view, (SubghzTestBasicModel * model) {
|
||||
osTimerStop(subghz_test_basic->timer);
|
||||
api_hal_subghz_idle();
|
||||
|
||||
if(event->type == InputTypeShort) {
|
||||
if(event->key == InputKeyLeft) {
|
||||
if(model->frequency > 0) model->frequency--;
|
||||
} else if(event->key == InputKeyRight) {
|
||||
if(model->frequency < subghz_frequencies_count - 1) model->frequency++;
|
||||
} else if(event->key == InputKeyDown) {
|
||||
if(model->path > 0) model->path--;
|
||||
} else if(event->key == InputKeyUp) {
|
||||
if(model->path < ApiHalSubGhzPath3) model->path++;
|
||||
}
|
||||
|
||||
model->real_frequency =
|
||||
api_hal_subghz_set_frequency(subghz_frequencies[model->frequency]);
|
||||
api_hal_subghz_set_path(model->path);
|
||||
}
|
||||
|
||||
if(event->key == InputKeyOk) {
|
||||
if(event->type == InputTypePress) {
|
||||
model->status = SubghzTestBasicModelStatusTx;
|
||||
} else if(event->type == InputTypeRelease) {
|
||||
model->status = SubghzTestBasicModelStatusRx;
|
||||
}
|
||||
}
|
||||
|
||||
if(model->status == SubghzTestBasicModelStatusRx) {
|
||||
gpio_init(&cc1101_g0_gpio, GpioModeInput);
|
||||
api_hal_subghz_rx();
|
||||
osTimerStart(subghz_test_basic->timer, 1024 / 4);
|
||||
} else {
|
||||
gpio_init(&cc1101_g0_gpio, GpioModeOutputPushPull);
|
||||
gpio_write(&cc1101_g0_gpio, false);
|
||||
api_hal_subghz_tx();
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_test_basic_enter(void* context) {
|
||||
furi_assert(context);
|
||||
SubghzTestBasic* subghz_test_basic = context;
|
||||
|
||||
api_hal_subghz_reset();
|
||||
api_hal_subghz_load_preset(ApiHalSubGhzPresetOokAsync);
|
||||
|
||||
gpio_init(&cc1101_g0_gpio, GpioModeInput);
|
||||
|
||||
with_view_model(
|
||||
subghz_test_basic->view, (SubghzTestBasicModel * model) {
|
||||
model->frequency = 4; // 433
|
||||
model->real_frequency =
|
||||
api_hal_subghz_set_frequency(subghz_frequencies[model->frequency]);
|
||||
model->path = ApiHalSubGhzPathIsolate; // isolate
|
||||
model->rssi = 0.0f;
|
||||
model->status = SubghzTestBasicModelStatusRx;
|
||||
return true;
|
||||
});
|
||||
|
||||
api_hal_subghz_rx();
|
||||
|
||||
osTimerStart(subghz_test_basic->timer, 1024 / 4);
|
||||
}
|
||||
|
||||
void subghz_test_basic_exit(void* context) {
|
||||
furi_assert(context);
|
||||
SubghzTestBasic* subghz_test_basic = context;
|
||||
|
||||
osTimerStop(subghz_test_basic->timer);
|
||||
|
||||
// Reinitialize IC to default state
|
||||
api_hal_subghz_init();
|
||||
}
|
||||
|
||||
void subghz_test_basic_rssi_timer_callback(void* context) {
|
||||
furi_assert(context);
|
||||
SubghzTestBasic* subghz_test_basic = context;
|
||||
|
||||
with_view_model(
|
||||
subghz_test_basic->view, (SubghzTestBasicModel * model) {
|
||||
model->rssi = api_hal_subghz_get_rssi();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
uint32_t subghz_test_basic_back(void* context) {
|
||||
return SubGhzViewMenu;
|
||||
}
|
||||
|
||||
SubghzTestBasic* subghz_test_basic_alloc() {
|
||||
SubghzTestBasic* subghz_test_basic = furi_alloc(sizeof(SubghzTestBasic));
|
||||
|
||||
// View allocation and configuration
|
||||
subghz_test_basic->view = view_alloc();
|
||||
view_allocate_model(
|
||||
subghz_test_basic->view, ViewModelTypeLockFree, sizeof(SubghzTestBasicModel));
|
||||
view_set_context(subghz_test_basic->view, subghz_test_basic);
|
||||
view_set_draw_callback(subghz_test_basic->view, (ViewDrawCallback)subghz_test_basic_draw);
|
||||
view_set_input_callback(subghz_test_basic->view, subghz_test_basic_input);
|
||||
view_set_enter_callback(subghz_test_basic->view, subghz_test_basic_enter);
|
||||
view_set_exit_callback(subghz_test_basic->view, subghz_test_basic_exit);
|
||||
view_set_previous_callback(subghz_test_basic->view, subghz_test_basic_back);
|
||||
|
||||
subghz_test_basic->timer = osTimerNew(
|
||||
subghz_test_basic_rssi_timer_callback, osTimerPeriodic, subghz_test_basic, NULL);
|
||||
|
||||
return subghz_test_basic;
|
||||
}
|
||||
|
||||
void subghz_test_basic_free(SubghzTestBasic* subghz_test_basic) {
|
||||
furi_assert(subghz_test_basic);
|
||||
osTimerDelete(subghz_test_basic->timer);
|
||||
view_free(subghz_test_basic->view);
|
||||
free(subghz_test_basic);
|
||||
}
|
||||
|
||||
View* subghz_test_basic_get_view(SubghzTestBasic* subghz_test_basic) {
|
||||
furi_assert(subghz_test_basic);
|
||||
return subghz_test_basic->view;
|
||||
}
|
11
applications/subghz/subghz_test_basic.h
Normal file
11
applications/subghz/subghz_test_basic.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
|
||||
typedef struct SubghzTestBasic SubghzTestBasic;
|
||||
|
||||
SubghzTestBasic* subghz_test_basic_alloc();
|
||||
|
||||
void subghz_test_basic_free(SubghzTestBasic* subghz_test_basic);
|
||||
|
||||
View* subghz_test_basic_get_view(SubghzTestBasic* subghz_test_basic);
|
210
applications/subghz/subghz_test_packet.c
Normal file
210
applications/subghz/subghz_test_packet.c
Normal file
@ -0,0 +1,210 @@
|
||||
#include "subghz_test_packet.h"
|
||||
#include "subghz_i.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <furi.h>
|
||||
#include <api-hal.h>
|
||||
#include <input/input.h>
|
||||
|
||||
static const uint8_t subghz_test_packet_data[] = {
|
||||
0x30, // 48bytes to transmit
|
||||
'F', 'L', 'I', 'P', 'P', 'E', 'R', ' ', 'T', 'E', 'S', 'T', ' ', 'P', 'A', 'C',
|
||||
'K', 'E', 'T', ' ', 'D', 'A', 'T', 'A', ' ', 'A', 'N', 'D', ' ', 'P', 'A', 'D',
|
||||
'F', 'L', 'I', 'P', 'P', 'E', 'R', ' ', 'T', 'E', 'S', 'T', ' ', 'P', 'A', 'C',
|
||||
|
||||
};
|
||||
|
||||
struct SubghzTestPacket {
|
||||
View* view;
|
||||
osTimerId timer;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
SubghzTestPacketModelStatusRx,
|
||||
SubghzTestPacketModelStatusTx,
|
||||
} SubghzTestPacketModelStatus;
|
||||
|
||||
typedef struct {
|
||||
uint8_t frequency;
|
||||
uint32_t real_frequency;
|
||||
ApiHalSubGhzPath path;
|
||||
float rssi;
|
||||
SubghzTestPacketModelStatus status;
|
||||
} SubghzTestPacketModel;
|
||||
|
||||
void subghz_test_packet_draw(Canvas* canvas, SubghzTestPacketModel* model) {
|
||||
char buffer[64];
|
||||
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str(canvas, 2, 12, "CC1101 Packet Test");
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
// Frequency
|
||||
snprintf(
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
"Freq: %03ld.%03ld.%03ld Hz",
|
||||
model->real_frequency / 1000000 % 1000,
|
||||
model->real_frequency / 1000 % 1000,
|
||||
model->real_frequency % 1000);
|
||||
canvas_draw_str(canvas, 2, 24, buffer);
|
||||
// Path
|
||||
char* path_name = "Unknown";
|
||||
if(model->path == ApiHalSubGhzPathIsolate) {
|
||||
path_name = "isolate";
|
||||
} else if(model->path == ApiHalSubGhzPath1) {
|
||||
path_name = "433MHz";
|
||||
} else if(model->path == ApiHalSubGhzPath2) {
|
||||
path_name = "315MHz";
|
||||
} else if(model->path == ApiHalSubGhzPath3) {
|
||||
path_name = "868MHz";
|
||||
}
|
||||
snprintf(buffer, sizeof(buffer), "Path: %d - %s", model->path, path_name);
|
||||
canvas_draw_str(canvas, 2, 36, buffer);
|
||||
if(model->status == SubghzTestPacketModelStatusRx) {
|
||||
snprintf(
|
||||
buffer,
|
||||
sizeof(buffer),
|
||||
"RSSI: %ld.%ld dBm",
|
||||
(int32_t)(model->rssi),
|
||||
(int32_t)fabs(model->rssi * 10) % 10);
|
||||
canvas_draw_str(canvas, 2, 48, buffer);
|
||||
} else {
|
||||
canvas_draw_str(canvas, 2, 48, "TX");
|
||||
}
|
||||
}
|
||||
|
||||
bool subghz_test_packet_input(InputEvent* event, void* context) {
|
||||
furi_assert(context);
|
||||
SubghzTestPacket* subghz_test_packet = context;
|
||||
|
||||
if(event->key == InputKeyBack) {
|
||||
return false;
|
||||
}
|
||||
|
||||
with_view_model(
|
||||
subghz_test_packet->view, (SubghzTestPacketModel * model) {
|
||||
osTimerStop(subghz_test_packet->timer);
|
||||
api_hal_subghz_idle();
|
||||
|
||||
if(event->type == InputTypeShort) {
|
||||
if(event->key == InputKeyLeft) {
|
||||
if(model->frequency > 0) model->frequency--;
|
||||
} else if(event->key == InputKeyRight) {
|
||||
if(model->frequency < subghz_frequencies_count - 1) model->frequency++;
|
||||
} else if(event->key == InputKeyDown) {
|
||||
if(model->path > 0) model->path--;
|
||||
} else if(event->key == InputKeyUp) {
|
||||
if(model->path < ApiHalSubGhzPath3) model->path++;
|
||||
}
|
||||
|
||||
model->real_frequency =
|
||||
api_hal_subghz_set_frequency(subghz_frequencies[model->frequency]);
|
||||
api_hal_subghz_set_path(model->path);
|
||||
}
|
||||
|
||||
if(event->key == InputKeyOk) {
|
||||
if(event->type == InputTypePress) {
|
||||
model->status = SubghzTestPacketModelStatusTx;
|
||||
} else if(event->type == InputTypeRelease) {
|
||||
model->status = SubghzTestPacketModelStatusRx;
|
||||
}
|
||||
}
|
||||
|
||||
if(model->status == SubghzTestPacketModelStatusRx) {
|
||||
api_hal_subghz_rx();
|
||||
osTimerStart(subghz_test_packet->timer, 1024 / 4);
|
||||
} else {
|
||||
api_hal_subghz_write_packet(
|
||||
subghz_test_packet_data, sizeof(subghz_test_packet_data));
|
||||
api_hal_subghz_tx();
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void subghz_test_packet_enter(void* context) {
|
||||
furi_assert(context);
|
||||
SubghzTestPacket* subghz_test_packet = context;
|
||||
|
||||
api_hal_subghz_reset();
|
||||
api_hal_subghz_load_preset(ApiHalSubGhzPreset2FskPacket);
|
||||
|
||||
gpio_init(&cc1101_g0_gpio, GpioModeInput);
|
||||
|
||||
with_view_model(
|
||||
subghz_test_packet->view, (SubghzTestPacketModel * model) {
|
||||
model->frequency = 4; // 433
|
||||
model->real_frequency =
|
||||
api_hal_subghz_set_frequency(subghz_frequencies[model->frequency]);
|
||||
model->path = ApiHalSubGhzPathIsolate; // isolate
|
||||
model->rssi = 0.0f;
|
||||
model->status = SubghzTestPacketModelStatusRx;
|
||||
return true;
|
||||
});
|
||||
|
||||
api_hal_subghz_rx();
|
||||
|
||||
osTimerStart(subghz_test_packet->timer, 1024 / 4);
|
||||
}
|
||||
|
||||
void subghz_test_packet_exit(void* context) {
|
||||
furi_assert(context);
|
||||
SubghzTestPacket* subghz_test_packet = context;
|
||||
|
||||
osTimerStop(subghz_test_packet->timer);
|
||||
|
||||
// Reinitialize IC to default state
|
||||
api_hal_subghz_init();
|
||||
}
|
||||
|
||||
void subghz_test_packet_rssi_timer_callback(void* context) {
|
||||
furi_assert(context);
|
||||
SubghzTestPacket* subghz_test_packet = context;
|
||||
|
||||
with_view_model(
|
||||
subghz_test_packet->view, (SubghzTestPacketModel * model) {
|
||||
model->rssi = api_hal_subghz_get_rssi();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
uint32_t subghz_test_packet_back(void* context) {
|
||||
return SubGhzViewMenu;
|
||||
}
|
||||
|
||||
SubghzTestPacket* subghz_test_packet_alloc() {
|
||||
SubghzTestPacket* subghz_test_packet = furi_alloc(sizeof(SubghzTestPacket));
|
||||
|
||||
// View allocation and configuration
|
||||
subghz_test_packet->view = view_alloc();
|
||||
view_allocate_model(
|
||||
subghz_test_packet->view, ViewModelTypeLockFree, sizeof(SubghzTestPacketModel));
|
||||
view_set_context(subghz_test_packet->view, subghz_test_packet);
|
||||
view_set_draw_callback(subghz_test_packet->view, (ViewDrawCallback)subghz_test_packet_draw);
|
||||
view_set_input_callback(subghz_test_packet->view, subghz_test_packet_input);
|
||||
view_set_enter_callback(subghz_test_packet->view, subghz_test_packet_enter);
|
||||
view_set_exit_callback(subghz_test_packet->view, subghz_test_packet_exit);
|
||||
view_set_previous_callback(subghz_test_packet->view, subghz_test_packet_back);
|
||||
|
||||
subghz_test_packet->timer = osTimerNew(
|
||||
subghz_test_packet_rssi_timer_callback, osTimerPeriodic, subghz_test_packet, NULL);
|
||||
|
||||
return subghz_test_packet;
|
||||
}
|
||||
|
||||
void subghz_test_packet_free(SubghzTestPacket* subghz_test_packet) {
|
||||
furi_assert(subghz_test_packet);
|
||||
osTimerDelete(subghz_test_packet->timer);
|
||||
view_free(subghz_test_packet->view);
|
||||
free(subghz_test_packet);
|
||||
}
|
||||
|
||||
View* subghz_test_packet_get_view(SubghzTestPacket* subghz_test_packet) {
|
||||
furi_assert(subghz_test_packet);
|
||||
return subghz_test_packet->view;
|
||||
}
|
11
applications/subghz/subghz_test_packet.h
Normal file
11
applications/subghz/subghz_test_packet.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/view.h>
|
||||
|
||||
typedef struct SubghzTestPacket SubghzTestPacket;
|
||||
|
||||
SubghzTestPacket* subghz_test_packet_alloc();
|
||||
|
||||
void subghz_test_packet_free(SubghzTestPacket* subghz_test_packet);
|
||||
|
||||
View* subghz_test_packet_get_view(SubghzTestPacket* subghz_test_packet);
|
@ -1,95 +0,0 @@
|
||||
#include "subghz-view-spectrum-settings.h"
|
||||
#include <callback-connector.h>
|
||||
|
||||
struct SpectrumSettingsModel {
|
||||
uint32_t start_freq;
|
||||
};
|
||||
|
||||
/***************************************************************************************/
|
||||
|
||||
static void draw_callback(Canvas* canvas, void* _model) {
|
||||
SpectrumSettingsModel* model = static_cast<SpectrumSettingsModel*>(_model);
|
||||
const uint8_t str_size = 64;
|
||||
char str_buffer[str_size];
|
||||
|
||||
canvas_clear(canvas);
|
||||
snprintf(str_buffer, str_size, "Start freq < %ld > MHz", model->start_freq);
|
||||
canvas_draw_str_aligned(canvas, 64, 32, AlignCenter, AlignCenter, str_buffer);
|
||||
}
|
||||
|
||||
static bool input_callback(InputEvent* event, void* context) {
|
||||
SubghzViewSpectrumSettings* _this = static_cast<SubghzViewSpectrumSettings*>(context);
|
||||
|
||||
bool consumed = false;
|
||||
|
||||
// Process key presses only
|
||||
if(event->type == InputTypeShort) {
|
||||
if(event->key == InputKeyOk) {
|
||||
_this->call_ok_callback();
|
||||
consumed = true;
|
||||
} else if(event->key == InputKeyLeft) {
|
||||
with_view_model_cpp(_this->get_view(), SpectrumSettingsModel, model, {
|
||||
model->start_freq--;
|
||||
return true;
|
||||
});
|
||||
consumed = true;
|
||||
} else if(event->key == InputKeyRight) {
|
||||
with_view_model_cpp(_this->get_view(), SpectrumSettingsModel, model, {
|
||||
model->start_freq++;
|
||||
return true;
|
||||
});
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
/***************************************************************************************/
|
||||
|
||||
View* SubghzViewSpectrumSettings::get_view() {
|
||||
return view;
|
||||
}
|
||||
|
||||
void SubghzViewSpectrumSettings::set_ok_callback(OkCallback callback, void* context) {
|
||||
ok_callback = callback;
|
||||
ok_callback_context = context;
|
||||
}
|
||||
|
||||
void SubghzViewSpectrumSettings::call_ok_callback() {
|
||||
if(ok_callback != nullptr) {
|
||||
ok_callback(ok_callback_context);
|
||||
}
|
||||
}
|
||||
|
||||
void SubghzViewSpectrumSettings::set_start_freq(uint32_t start_freq) {
|
||||
with_view_model_cpp(view, SpectrumSettingsModel, model, {
|
||||
model->start_freq = start_freq;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
uint32_t SubghzViewSpectrumSettings::get_start_freq() {
|
||||
uint32_t result;
|
||||
|
||||
with_view_model_cpp(view, SpectrumSettingsModel, model, {
|
||||
result = model->start_freq;
|
||||
return false;
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
SubghzViewSpectrumSettings::SubghzViewSpectrumSettings() {
|
||||
view = view_alloc();
|
||||
view_set_context(view, this);
|
||||
view_allocate_model(view, ViewModelTypeLocking, sizeof(SpectrumSettingsModel));
|
||||
|
||||
view_set_draw_callback(view, draw_callback);
|
||||
|
||||
view_set_input_callback(view, input_callback);
|
||||
}
|
||||
|
||||
SubghzViewSpectrumSettings::~SubghzViewSpectrumSettings() {
|
||||
view_free(view);
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
#include <gui/view.h>
|
||||
|
||||
class SubghzViewSpectrumSettings {
|
||||
public:
|
||||
SubghzViewSpectrumSettings();
|
||||
~SubghzViewSpectrumSettings();
|
||||
|
||||
View* get_view();
|
||||
|
||||
// ok callback methods
|
||||
typedef void (*OkCallback)(void* context);
|
||||
void set_ok_callback(OkCallback callback, void* context);
|
||||
void call_ok_callback();
|
||||
|
||||
// model data getters/setters
|
||||
void set_start_freq(uint32_t start_freq);
|
||||
uint32_t get_start_freq();
|
||||
|
||||
private:
|
||||
View* view;
|
||||
|
||||
// ok callback data
|
||||
OkCallback ok_callback = nullptr;
|
||||
void* ok_callback_context = nullptr;
|
||||
};
|
@ -55,7 +55,7 @@ flash bank $_FLASHNAME stm32l4x 0 0 0 0 $_TARGETNAME
|
||||
#
|
||||
# Note that there is a pretty wide band where things are
|
||||
# more or less stable, see http://openocd.zylin.com/#/c/3366/
|
||||
adapter speed 8000
|
||||
adapter speed 24000
|
||||
|
||||
adapter srst delay 100
|
||||
if {[using_jtag]} {
|
||||
@ -77,12 +77,12 @@ $_TARGETNAME configure -event reset-init {
|
||||
mmw 0x58004000 0x00000102 0 ;# FLASH_ACR |= PRFTBE | 2(Latency)
|
||||
mmw 0x58000000 0x00000091 0 ;# RCC_CR = MSI_ON | MSI Range 24 MHz
|
||||
# Boost JTAG frequency
|
||||
adapter speed 8000
|
||||
adapter speed 24000
|
||||
}
|
||||
|
||||
$_TARGETNAME configure -event reset-start {
|
||||
# Reset clock is MSI (4 MHz)
|
||||
adapter speed 8000
|
||||
adapter speed 24000
|
||||
}
|
||||
|
||||
$_TARGETNAME configure -event examine-end {
|
||||
|
@ -1,23 +1,98 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Sub-GHz band type */
|
||||
/** Radio Presets */
|
||||
typedef enum {
|
||||
RfBandIsolation = 0,
|
||||
RfBand1 = 1,
|
||||
RfBand2 = 2,
|
||||
RfBand3 = 3
|
||||
} RfBand;
|
||||
ApiHalSubGhzPresetOokAsync, /** OOK, asynchronous */
|
||||
ApiHalSubGhzPreset2FskPacket, /** 2FSK, 115kBaud, variable packet length */
|
||||
} ApiHalSubGhzPreset;
|
||||
|
||||
/**
|
||||
* Set Sub-GHz band
|
||||
* @param band RfBand
|
||||
/** Switchable Radio Paths */
|
||||
typedef enum {
|
||||
ApiHalSubGhzPathIsolate, /** Isolate Radio from antenna */
|
||||
ApiHalSubGhzPath1, /** Path 1: SW1RF1-SW2RF2, LCLCL */
|
||||
ApiHalSubGhzPath2, /** Path 2: SW1RF2-SW2RF1, LCLCLCL */
|
||||
ApiHalSubGhzPath3, /** Path 3: SW1RF3-SW2RF3, LCLC */
|
||||
} ApiHalSubGhzPath;
|
||||
|
||||
/** Initialize and switch to power save mode
|
||||
* Used by internal API-HAL initalization routine
|
||||
* Can be used to reinitialize device to safe state and send it to sleep
|
||||
*/
|
||||
void api_hal_rf_band_set(RfBand band);
|
||||
void api_hal_subghz_init();
|
||||
|
||||
/** Dump info to stdout */
|
||||
void api_hal_subghz_dump_state();
|
||||
|
||||
/** Load registers from preset by preset name
|
||||
* @param preset to load
|
||||
*/
|
||||
void api_hal_subghz_load_preset(ApiHalSubGhzPreset preset);
|
||||
|
||||
/** Load registers
|
||||
* @param register-value pairs array, terminated with {0,0}
|
||||
*/
|
||||
void api_hal_subghz_load_registers(const uint8_t data[][2]);
|
||||
|
||||
/** Load PATABLE
|
||||
* @param data, 8 uint8_t values
|
||||
*/
|
||||
void api_hal_subghz_load_patable(const uint8_t data[8]);
|
||||
|
||||
/** Write packet to FIFO
|
||||
* @param data, bytes array
|
||||
* @param size, size
|
||||
*/
|
||||
void api_hal_subghz_write_packet(const uint8_t* data, uint8_t size);
|
||||
|
||||
/** Read packet from FIFO
|
||||
* @param data, pointer
|
||||
* @param size, size
|
||||
*/
|
||||
void api_hal_subghz_read_packet(uint8_t* data, uint8_t size);
|
||||
|
||||
/** Shutdown
|
||||
* Issue spwd command
|
||||
* @warning registers content will be lost
|
||||
*/
|
||||
void api_hal_subghz_shutdown();
|
||||
|
||||
/** Reset
|
||||
* Issue reset command
|
||||
* @warning registers content will be lost
|
||||
*/
|
||||
void api_hal_subghz_reset();
|
||||
|
||||
/** Switch to Idle */
|
||||
void api_hal_subghz_idle();
|
||||
|
||||
/** Switch to Recieve */
|
||||
void api_hal_subghz_rx();
|
||||
|
||||
/** Switch to Transmit */
|
||||
void api_hal_subghz_tx();
|
||||
|
||||
/** Get RSSI value in dBm */
|
||||
float api_hal_subghz_get_rssi();
|
||||
|
||||
/** Set frequency
|
||||
* @param frequency in herz
|
||||
* @return real frequency in herz
|
||||
*/
|
||||
uint32_t api_hal_subghz_set_frequency(uint32_t value);
|
||||
|
||||
/** Set path
|
||||
* @param radio path to use
|
||||
*/
|
||||
void api_hal_subghz_set_path(ApiHalSubGhzPath path);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1,153 +1,103 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file : main.h
|
||||
* @brief : Header for main.c file.
|
||||
* This file contains the common defines of the application.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under Ultimate Liberty license
|
||||
* SLA0044, the "License"; You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* www.st.com/SLA0044
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __MAIN_H
|
||||
#define __MAIN_H
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32wbxx_hal.h"
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN ET */
|
||||
|
||||
/* USER CODE END ET */
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EC */
|
||||
|
||||
/* USER CODE END EC */
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EM */
|
||||
|
||||
/* USER CODE END EM */
|
||||
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
void Error_Handler(void);
|
||||
|
||||
/* USER CODE BEGIN EFP */
|
||||
|
||||
/* USER CODE END EFP */
|
||||
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
#define BUTTON_BACK_Pin GPIO_PIN_13
|
||||
#define BUTTON_BACK_GPIO_Port GPIOC
|
||||
#define BUTTON_BACK_EXTI_IRQn EXTI15_10_IRQn
|
||||
#define QUARTZ_32MHZ_IN_Pin GPIO_PIN_14
|
||||
#define QUARTZ_32MHZ_IN_GPIO_Port GPIOC
|
||||
#define QUARTZ_32MHZ_OUT_Pin GPIO_PIN_15
|
||||
#define QUARTZ_32MHZ_OUT_GPIO_Port GPIOC
|
||||
#define BUTTON_OK_Pin GPIO_PIN_3
|
||||
#define BUTTON_OK_GPIO_Port GPIOH
|
||||
#define BUTTON_OK_EXTI_IRQn EXTI3_IRQn
|
||||
#define SPEAKER_Pin GPIO_PIN_8
|
||||
#define SPEAKER_GPIO_Port GPIOB
|
||||
#define IR_TX_Pin GPIO_PIN_9
|
||||
#define IR_TX_GPIO_Port GPIOB
|
||||
#define PC0_Pin GPIO_PIN_0
|
||||
#define PC0_GPIO_Port GPIOC
|
||||
#define PC1_Pin GPIO_PIN_1
|
||||
#define PC1_GPIO_Port GPIOC
|
||||
#define PC3_Pin GPIO_PIN_3
|
||||
#define PC3_GPIO_Port GPIOC
|
||||
#define IR_RX_Pin GPIO_PIN_0
|
||||
#define IR_RX_GPIO_Port GPIOA
|
||||
#define LED_RED_Pin GPIO_PIN_1
|
||||
#define LED_RED_GPIO_Port GPIOA
|
||||
#define LED_GREEN_Pin GPIO_PIN_2
|
||||
#define LED_GREEN_GPIO_Port GPIOA
|
||||
#define LED_BLUE_Pin GPIO_PIN_3
|
||||
#define LED_BLUE_GPIO_Port GPIOA
|
||||
#define PA4_Pin GPIO_PIN_4
|
||||
#define PA4_GPIO_Port GPIOA
|
||||
#define SPI_R_SCK_Pin GPIO_PIN_5
|
||||
#define SPI_R_SCK_GPIO_Port GPIOA
|
||||
#define PA6_Pin GPIO_PIN_6
|
||||
#define PA6_GPIO_Port GPIOA
|
||||
#define PA7_Pin GPIO_PIN_7
|
||||
#define PA7_GPIO_Port GPIOA
|
||||
#define RFID_PULL_Pin GPIO_PIN_8
|
||||
#define RFID_PULL_GPIO_Port GPIOA
|
||||
#define RFID_PULL_EXTI_IRQn EXTI9_5_IRQn
|
||||
#define CC1101_G0_Pin GPIO_PIN_4
|
||||
#define CC1101_G0_GPIO_Port GPIOC
|
||||
#define RFID_RF_IN_Pin GPIO_PIN_5
|
||||
#define RFID_RF_IN_GPIO_Port GPIOC
|
||||
#define PB2_Pin GPIO_PIN_2
|
||||
#define PB2_GPIO_Port GPIOB
|
||||
#define BUTTON_UP_Pin GPIO_PIN_10
|
||||
#define BUTTON_UP_GPIO_Port GPIOB
|
||||
#define BUTTON_UP_EXTI_IRQn EXTI15_10_IRQn
|
||||
#define BUTTON_LEFT_Pin GPIO_PIN_11
|
||||
#define BUTTON_LEFT_GPIO_Port GPIOB
|
||||
#define BUTTON_LEFT_EXTI_IRQn EXTI15_10_IRQn
|
||||
#define DISPLAY_RST_Pin GPIO_PIN_0
|
||||
#define DISPLAY_RST_GPIO_Port GPIOB
|
||||
#define BUTTON_DOWN_Pin GPIO_PIN_1
|
||||
#define BUTTON_DOWN_GPIO_Port GPIOB
|
||||
#define BUTTON_BACK_GPIO_Port GPIOC
|
||||
#define BUTTON_BACK_Pin GPIO_PIN_13
|
||||
#define BUTTON_DOWN_EXTI_IRQn EXTI1_IRQn
|
||||
#define NFC_CS_Pin GPIO_PIN_4
|
||||
#define NFC_CS_GPIO_Port GPIOE
|
||||
#define BUTTON_RIGHT_Pin GPIO_PIN_12
|
||||
#define BUTTON_RIGHT_GPIO_Port GPIOB
|
||||
#define BUTTON_DOWN_GPIO_Port GPIOB
|
||||
#define BUTTON_DOWN_Pin GPIO_PIN_1
|
||||
#define BUTTON_LEFT_EXTI_IRQn EXTI15_10_IRQn
|
||||
#define BUTTON_LEFT_GPIO_Port GPIOB
|
||||
#define BUTTON_LEFT_Pin GPIO_PIN_11
|
||||
#define BUTTON_OK_EXTI_IRQn EXTI3_IRQn
|
||||
#define BUTTON_OK_GPIO_Port GPIOH
|
||||
#define BUTTON_OK_Pin GPIO_PIN_3
|
||||
#define BUTTON_RIGHT_EXTI_IRQn EXTI15_10_IRQn
|
||||
#define RFID_OUT_Pin GPIO_PIN_13
|
||||
#define RFID_OUT_GPIO_Port GPIOB
|
||||
#define iBTN_Pin GPIO_PIN_14
|
||||
#define iBTN_GPIO_Port GPIOB
|
||||
#define SPI_D_MOSI_Pin GPIO_PIN_15
|
||||
#define SPI_D_MOSI_GPIO_Port GPIOB
|
||||
#define DISPLAY_DI_Pin GPIO_PIN_6
|
||||
#define DISPLAY_DI_GPIO_Port GPIOC
|
||||
#define DISPLAY_BACKLIGHT_Pin GPIO_PIN_15
|
||||
#define DISPLAY_BACKLIGHT_GPIO_Port GPIOA
|
||||
#define PC10_Pin GPIO_PIN_10
|
||||
#define PC10_GPIO_Port GPIOC
|
||||
#define DISPLAY_CS_Pin GPIO_PIN_11
|
||||
#define DISPLAY_CS_GPIO_Port GPIOC
|
||||
#define SD_CS_Pin GPIO_PIN_12
|
||||
#define SD_CS_GPIO_Port GPIOC
|
||||
#define CC1101_CS_Pin GPIO_PIN_0
|
||||
#define BUTTON_RIGHT_GPIO_Port GPIOB
|
||||
#define BUTTON_RIGHT_Pin GPIO_PIN_12
|
||||
#define BUTTON_UP_EXTI_IRQn EXTI15_10_IRQn
|
||||
#define BUTTON_UP_GPIO_Port GPIOB
|
||||
#define BUTTON_UP_Pin GPIO_PIN_10
|
||||
#define CC1101_CS_GPIO_Port GPIOD
|
||||
#define SPI_D_SCK_Pin GPIO_PIN_1
|
||||
#define SPI_D_SCK_GPIO_Port GPIOD
|
||||
#define PB3_Pin GPIO_PIN_3
|
||||
#define CC1101_CS_Pin GPIO_PIN_0
|
||||
#define CC1101_G0_GPIO_Port GPIOC
|
||||
#define CC1101_G0_Pin GPIO_PIN_4
|
||||
#define DISPLAY_BACKLIGHT_GPIO_Port GPIOA
|
||||
#define DISPLAY_BACKLIGHT_Pin GPIO_PIN_15
|
||||
#define DISPLAY_CS_GPIO_Port GPIOC
|
||||
#define DISPLAY_CS_Pin GPIO_PIN_11
|
||||
#define DISPLAY_DI_GPIO_Port GPIOC
|
||||
#define DISPLAY_DI_Pin GPIO_PIN_6
|
||||
#define DISPLAY_RST_GPIO_Port GPIOB
|
||||
#define DISPLAY_RST_Pin GPIO_PIN_0
|
||||
#define IR_RX_GPIO_Port GPIOA
|
||||
#define IR_RX_Pin GPIO_PIN_0
|
||||
#define IR_TX_GPIO_Port GPIOB
|
||||
#define IR_TX_Pin GPIO_PIN_9
|
||||
#define LED_BLUE_GPIO_Port GPIOA
|
||||
#define LED_BLUE_Pin GPIO_PIN_3
|
||||
#define LED_GREEN_GPIO_Port GPIOA
|
||||
#define LED_GREEN_Pin GPIO_PIN_2
|
||||
#define LED_RED_GPIO_Port GPIOA
|
||||
#define LED_RED_Pin GPIO_PIN_1
|
||||
#define NFC_CS_GPIO_Port GPIOE
|
||||
#define NFC_CS_Pin GPIO_PIN_4
|
||||
#define PA4_GPIO_Port GPIOA
|
||||
#define PA4_Pin GPIO_PIN_4
|
||||
#define PA6_GPIO_Port GPIOA
|
||||
#define PA6_Pin GPIO_PIN_6
|
||||
#define PA7_GPIO_Port GPIOA
|
||||
#define PA7_Pin GPIO_PIN_7
|
||||
#define PB2_GPIO_Port GPIOB
|
||||
#define PB2_Pin GPIO_PIN_2
|
||||
#define PB3_GPIO_Port GPIOB
|
||||
#define SPI_R_MISO_Pin GPIO_PIN_4
|
||||
#define SPI_R_MISO_GPIO_Port GPIOB
|
||||
#define SPI_R_MOSI_Pin GPIO_PIN_5
|
||||
#define SPI_R_MOSI_GPIO_Port GPIOB
|
||||
/* USER CODE BEGIN Private defines */
|
||||
#define PB3_Pin GPIO_PIN_3
|
||||
#define PC0_GPIO_Port GPIOC
|
||||
#define PC0_Pin GPIO_PIN_0
|
||||
#define PC10_GPIO_Port GPIOC
|
||||
#define PC10_Pin GPIO_PIN_10
|
||||
#define PC1_GPIO_Port GPIOC
|
||||
#define PC1_Pin GPIO_PIN_1
|
||||
#define PC3_GPIO_Port GPIOC
|
||||
#define PC3_Pin GPIO_PIN_3
|
||||
#define QUARTZ_32MHZ_IN_GPIO_Port GPIOC
|
||||
#define QUARTZ_32MHZ_IN_Pin GPIO_PIN_14
|
||||
#define QUARTZ_32MHZ_OUT_GPIO_Port GPIOC
|
||||
#define QUARTZ_32MHZ_OUT_Pin GPIO_PIN_15
|
||||
#define RFID_OUT_GPIO_Port GPIOB
|
||||
#define RFID_OUT_Pin GPIO_PIN_13
|
||||
#define RFID_PULL_EXTI_IRQn EXTI9_5_IRQn
|
||||
#define RFID_PULL_GPIO_Port GPIOA
|
||||
#define RFID_PULL_Pin GPIO_PIN_8
|
||||
#define RFID_RF_IN_GPIO_Port GPIOC
|
||||
#define RFID_RF_IN_Pin GPIO_PIN_5
|
||||
#define SD_CS_GPIO_Port GPIOC
|
||||
#define SD_CS_Pin GPIO_PIN_12
|
||||
#define SPEAKER_GPIO_Port GPIOB
|
||||
#define SPEAKER_Pin GPIO_PIN_8
|
||||
#define iBTN_GPIO_Port GPIOB
|
||||
#define iBTN_Pin GPIO_PIN_14
|
||||
|
||||
#define MISO_PIN GpioPin{.port = SPI_R_MISO_GPIO_Port, .pin = SPI_R_MISO_Pin}
|
||||
#define SPI_D_MISO_GPIO_Port GPIOC
|
||||
#define SPI_D_MISO_Pin GPIO_PIN_2
|
||||
#define SPI_D_MOSI_GPIO_Port GPIOB
|
||||
#define SPI_D_MOSI_Pin GPIO_PIN_15
|
||||
#define SPI_D_SCK_GPIO_Port GPIOD
|
||||
#define SPI_D_SCK_Pin GPIO_PIN_1
|
||||
#define SPI_R_MISO_GPIO_Port GPIOB
|
||||
#define SPI_R_MISO_Pin GPIO_PIN_4
|
||||
#define SPI_R_MOSI_GPIO_Port GPIOB
|
||||
#define SPI_R_MOSI_Pin GPIO_PIN_5
|
||||
#define SPI_R_SCK_GPIO_Port GPIOA
|
||||
#define SPI_R_SCK_Pin GPIO_PIN_5
|
||||
|
||||
#define SPI_R hspi1
|
||||
#define SPI_D hspi2
|
||||
@ -183,12 +133,6 @@ extern TIM_HandleTypeDef htim16;
|
||||
#define VIBRO_Pin GPIO_PIN_10
|
||||
#define VIBRO_GPIO_Port GPIOC
|
||||
|
||||
/* USER CODE END Private defines */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __MAIN_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
@ -23,5 +23,6 @@ void delay_us(float microseconds) {
|
||||
void delay(float milliseconds) {
|
||||
uint32_t ticks = milliseconds / (1000.0f / osKernelGetTickFreq());
|
||||
osStatus_t result = osDelay(ticks);
|
||||
(void)result;
|
||||
assert(result == osOK);
|
||||
}
|
@ -4,35 +4,41 @@
|
||||
|
||||
const InputPin input_pins[] = {
|
||||
{.port = BUTTON_UP_GPIO_Port, .pin = BUTTON_UP_Pin, .key = InputKeyUp, .inverted = true},
|
||||
{.port = BUTTON_DOWN_GPIO_Port, .pin = BUTTON_DOWN_Pin, .key = InputKeyDown, .inverted = true},
|
||||
{.port = BUTTON_DOWN_GPIO_Port,
|
||||
.pin = BUTTON_DOWN_Pin,
|
||||
.key = InputKeyDown,
|
||||
.inverted = true},
|
||||
{.port = BUTTON_RIGHT_GPIO_Port,
|
||||
.pin = BUTTON_RIGHT_Pin,
|
||||
.key = InputKeyRight,
|
||||
.inverted = true},
|
||||
{.port = BUTTON_LEFT_GPIO_Port, .pin = BUTTON_LEFT_Pin, .key = InputKeyLeft, .inverted = true},
|
||||
{.port = BUTTON_LEFT_GPIO_Port,
|
||||
.pin = BUTTON_LEFT_Pin,
|
||||
.key = InputKeyLeft,
|
||||
.inverted = true},
|
||||
{.port = BUTTON_OK_GPIO_Port, .pin = BUTTON_OK_Pin, .key = InputKeyOk, .inverted = false},
|
||||
{.port = BUTTON_BACK_GPIO_Port, .pin = BUTTON_BACK_Pin, .key = InputKeyBack, .inverted = true},
|
||||
{.port = BUTTON_BACK_GPIO_Port,
|
||||
.pin = BUTTON_BACK_Pin,
|
||||
.key = InputKeyBack,
|
||||
.inverted = true},
|
||||
};
|
||||
|
||||
const size_t input_pins_count = sizeof(input_pins) / sizeof(InputPin);
|
||||
|
||||
const GpioPin led_gpio[3] = {
|
||||
{LED_RED_GPIO_Port, LED_RED_Pin},
|
||||
{LED_GREEN_GPIO_Port, LED_GREEN_Pin},
|
||||
{LED_BLUE_GPIO_Port, LED_BLUE_Pin}};
|
||||
|
||||
const GpioPin backlight_gpio = {DISPLAY_BACKLIGHT_GPIO_Port, DISPLAY_BACKLIGHT_Pin};
|
||||
const GpioPin sd_cs_gpio = {SD_CS_GPIO_Port, SD_CS_Pin};
|
||||
const GpioPin vibro_gpio = {VIBRO_GPIO_Port, VIBRO_Pin};
|
||||
const GpioPin ibutton_gpio = {iBTN_GPIO_Port, iBTN_Pin};
|
||||
const GpioPin cc1101_g0_gpio = {CC1101_G0_GPIO_Port, CC1101_G0_Pin};
|
||||
|
||||
// external gpio's
|
||||
const GpioPin ext_pc0_gpio = {GPIOC, GPIO_PIN_0};
|
||||
const GpioPin ext_pc1_gpio = {GPIOC, GPIO_PIN_1};
|
||||
const GpioPin ext_pc3_gpio = {GPIOC, GPIO_PIN_3};
|
||||
const GpioPin ext_pb2_gpio = {GPIOB, GPIO_PIN_2};
|
||||
const GpioPin ext_pb3_gpio = {GPIOB, GPIO_PIN_3};
|
||||
const GpioPin ext_pa4_gpio = {GPIOA, GPIO_PIN_4};
|
||||
const GpioPin ext_pa6_gpio = {GPIOA, GPIO_PIN_6};
|
||||
const GpioPin ext_pa7_gpio = {GPIOA, GPIO_PIN_7};
|
||||
const GpioPin gpio_subghz_cs = { .port=CC1101_CS_GPIO_Port, .pin=CC1101_CS_Pin };
|
||||
const GpioPin gpio_display_cs = { .port=DISPLAY_CS_GPIO_Port, .pin=DISPLAY_CS_Pin };
|
||||
const GpioPin gpio_display_rst = { .port=DISPLAY_RST_GPIO_Port, .pin=DISPLAY_RST_Pin };
|
||||
const GpioPin gpio_display_di = { .port=DISPLAY_DI_GPIO_Port, .pin=DISPLAY_DI_Pin };
|
||||
const GpioPin gpio_sdcard_cs = { .port=SD_CS_GPIO_Port, .pin=SD_CS_Pin };
|
||||
const GpioPin gpio_nfc_cs = { .port=NFC_CS_GPIO_Port, .pin=NFC_CS_Pin };
|
||||
|
||||
const GpioPin gpio_spi_d_miso = { .port=SPI_D_MISO_GPIO_Port, .pin=SPI_D_MISO_Pin };
|
||||
const GpioPin gpio_spi_d_mosi = { .port=SPI_D_MOSI_GPIO_Port, .pin=SPI_D_MOSI_Pin };
|
||||
const GpioPin gpio_spi_d_sck = { .port=SPI_D_SCK_GPIO_Port, .pin=SPI_D_SCK_Pin };
|
||||
const GpioPin gpio_spi_r_miso = { .port=SPI_R_MISO_GPIO_Port, .pin=SPI_R_MISO_Pin };
|
||||
const GpioPin gpio_spi_r_mosi = { .port=SPI_R_MOSI_GPIO_Port, .pin=SPI_R_MOSI_Pin };
|
||||
const GpioPin gpio_spi_r_sck = { .port=SPI_R_SCK_GPIO_Port, .pin=SPI_R_SCK_Pin };
|
||||
|
@ -16,7 +16,7 @@ extern "C" {
|
||||
#define POWER_I2C_SDA_GPIO_Port GPIOA
|
||||
|
||||
#define POWER_I2C I2C1
|
||||
/* Timing register value is computed with the STM32CubeMX Tool,
|
||||
/** Timing register value is computed with the STM32CubeMX Tool,
|
||||
* Fast Mode @100kHz with I2CCLK = 64 MHz,
|
||||
* rise time = 0ns, fall time = 0ns
|
||||
*/
|
||||
@ -53,20 +53,27 @@ typedef struct {
|
||||
extern const InputPin input_pins[];
|
||||
extern const size_t input_pins_count;
|
||||
|
||||
extern const GpioPin sd_cs_gpio;
|
||||
extern const GpioPin vibro_gpio;
|
||||
extern const GpioPin ibutton_gpio;
|
||||
extern const GpioPin cc1101_g0_gpio;
|
||||
|
||||
// external gpio's
|
||||
extern const GpioPin ext_pc0_gpio;
|
||||
extern const GpioPin ext_pc1_gpio;
|
||||
extern const GpioPin ext_pc3_gpio;
|
||||
extern const GpioPin ext_pb2_gpio;
|
||||
extern const GpioPin ext_pb3_gpio;
|
||||
extern const GpioPin ext_pa4_gpio;
|
||||
extern const GpioPin ext_pa6_gpio;
|
||||
extern const GpioPin ext_pa7_gpio;
|
||||
extern const GpioPin gpio_subghz_cs;
|
||||
extern const GpioPin gpio_display_cs;
|
||||
|
||||
extern const GpioPin gpio_subghz_cs;
|
||||
extern const GpioPin gpio_display_cs;
|
||||
extern const GpioPin gpio_display_rst;
|
||||
extern const GpioPin gpio_display_di;
|
||||
extern const GpioPin gpio_sdcard_cs;
|
||||
extern const GpioPin gpio_nfc_cs;
|
||||
|
||||
extern const GpioPin gpio_spi_d_miso;
|
||||
extern const GpioPin gpio_spi_d_mosi;
|
||||
extern const GpioPin gpio_spi_d_sck;
|
||||
extern const GpioPin gpio_spi_r_miso;
|
||||
extern const GpioPin gpio_spi_r_mosi;
|
||||
extern const GpioPin gpio_spi_r_sck;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -16,25 +16,21 @@ bool hal_sd_detect(void) {
|
||||
bool result = false;
|
||||
|
||||
// TODO open record
|
||||
const GpioPin* sd_cs_record = &sd_cs_gpio;
|
||||
|
||||
// TODO: SPI manager
|
||||
api_hal_spi_lock(sd_fast_spi.spi);
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSdCard);
|
||||
|
||||
// configure pin as input
|
||||
gpio_init_ex(sd_cs_record, GpioModeInput, GpioPullUp, GpioSpeedVeryHigh);
|
||||
gpio_init_ex(device->chip_select, GpioModeInput, GpioPullUp, GpioSpeedVeryHigh);
|
||||
delay(1);
|
||||
|
||||
// if gpio_read == 0 return true else return false
|
||||
result = !gpio_read(sd_cs_record);
|
||||
result = !gpio_read(device->chip_select);
|
||||
|
||||
// configure pin back
|
||||
gpio_init_ex(sd_cs_record, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
gpio_write(sd_cs_record, 1);
|
||||
gpio_init_ex(device->chip_select, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
gpio_write(device->chip_select, 1);
|
||||
delay(1);
|
||||
|
||||
// TODO: SPI manager
|
||||
api_hal_spi_unlock(sd_fast_spi.spi);
|
||||
api_hal_spi_device_return(device);
|
||||
|
||||
return result;
|
||||
}
|
@ -1,14 +1,89 @@
|
||||
#include "main.h"
|
||||
#include "api-hal-spi-config.h"
|
||||
#include <api-hal-spi-config.h>
|
||||
#include <api-hal-resources.h>
|
||||
|
||||
extern SPI_HandleTypeDef SPI_R;
|
||||
extern SPI_HandleTypeDef SPI_D;
|
||||
|
||||
const SPI_InitTypeDef api_hal_spi_config_nfc = {
|
||||
.Mode = SPI_MODE_MASTER,
|
||||
.Direction = SPI_DIRECTION_2LINES,
|
||||
.DataSize = SPI_DATASIZE_8BIT,
|
||||
.CLKPolarity = SPI_POLARITY_LOW,
|
||||
.CLKPhase = SPI_PHASE_2EDGE,
|
||||
.NSS = SPI_NSS_SOFT,
|
||||
.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8,
|
||||
.FirstBit = SPI_FIRSTBIT_MSB,
|
||||
.TIMode = SPI_TIMODE_DISABLE,
|
||||
.CRCCalculation = SPI_CRCCALCULATION_DISABLE,
|
||||
.CRCPolynomial = 7,
|
||||
.CRCLength = SPI_CRC_LENGTH_DATASIZE,
|
||||
.NSSPMode = SPI_NSS_PULSE_DISABLE,
|
||||
};
|
||||
|
||||
const SPI_InitTypeDef api_hal_spi_config_subghz = {
|
||||
.Mode = SPI_MODE_MASTER,
|
||||
.Direction = SPI_DIRECTION_2LINES,
|
||||
.DataSize = SPI_DATASIZE_8BIT,
|
||||
.CLKPolarity = SPI_POLARITY_LOW,
|
||||
.CLKPhase = SPI_PHASE_1EDGE,
|
||||
.NSS = SPI_NSS_SOFT,
|
||||
.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64,
|
||||
.FirstBit = SPI_FIRSTBIT_MSB,
|
||||
.TIMode = SPI_TIMODE_DISABLE,
|
||||
.CRCCalculation = SPI_CRCCALCULATION_DISABLE,
|
||||
.CRCPolynomial = 7,
|
||||
.CRCLength = SPI_CRC_LENGTH_DATASIZE,
|
||||
.NSSPMode = SPI_NSS_PULSE_DISABLE,
|
||||
};
|
||||
|
||||
const SPI_InitTypeDef api_hal_spi_config_display = {
|
||||
.Mode = SPI_MODE_MASTER,
|
||||
.Direction = SPI_DIRECTION_2LINES,
|
||||
.DataSize = SPI_DATASIZE_8BIT,
|
||||
.CLKPolarity = SPI_POLARITY_LOW,
|
||||
.CLKPhase = SPI_PHASE_1EDGE,
|
||||
.NSS = SPI_NSS_SOFT,
|
||||
.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16,
|
||||
.FirstBit = SPI_FIRSTBIT_MSB,
|
||||
.TIMode = SPI_TIMODE_DISABLE,
|
||||
.CRCCalculation = SPI_CRCCALCULATION_DISABLE,
|
||||
.CRCPolynomial = 7,
|
||||
.CRCLength = SPI_CRC_LENGTH_DATASIZE,
|
||||
.NSSPMode = SPI_NSS_PULSE_ENABLE,
|
||||
};
|
||||
|
||||
osMutexId_t spi_mutex_d = NULL;
|
||||
osMutexId_t spi_mutex_r = NULL;
|
||||
|
||||
const ApiHalSpiBus spi_r = {
|
||||
.spi=&SPI_R,
|
||||
.mutex=&spi_mutex_r,
|
||||
.miso=&gpio_spi_r_miso,
|
||||
.mosi=&gpio_spi_r_mosi,
|
||||
.clk=&gpio_spi_r_sck,
|
||||
};
|
||||
|
||||
const ApiHalSpiBus spi_d = {
|
||||
.spi=&SPI_D,
|
||||
.mutex=&spi_mutex_d,
|
||||
.miso=&gpio_spi_d_miso,
|
||||
.mosi=&gpio_spi_d_mosi,
|
||||
.clk=&gpio_spi_d_sck,
|
||||
};
|
||||
|
||||
const ApiHalSpiDevice api_hal_spi_devices[ApiHalSpiDeviceIdMax] = {
|
||||
{ .bus=&spi_r, .config=&api_hal_spi_config_subghz, .chip_select=&gpio_subghz_cs, },
|
||||
{ .bus=&spi_d, .config=&api_hal_spi_config_display, .chip_select=&gpio_display_cs, },
|
||||
{ .bus=&spi_d, .config=NULL, .chip_select=&gpio_sdcard_cs, },
|
||||
{ .bus=&spi_r, .config=&api_hal_spi_config_nfc, .chip_select=&gpio_nfc_cs },
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* SD Card in fast mode (after init)
|
||||
*/
|
||||
const SPIDevice sd_fast_spi = {
|
||||
.spi = &SPI_D,
|
||||
.bus= &spi_d,
|
||||
.config = {
|
||||
.Mode = SPI_MODE_MASTER,
|
||||
.Direction = SPI_DIRECTION_2LINES,
|
||||
@ -29,7 +104,7 @@ const SPIDevice sd_fast_spi = {
|
||||
* SD Card in slow mode (before init)
|
||||
*/
|
||||
const SPIDevice sd_slow_spi = {
|
||||
.spi = &SPI_D,
|
||||
.bus= &spi_d,
|
||||
.config = {
|
||||
.Mode = SPI_MODE_MASTER,
|
||||
.Direction = SPI_DIRECTION_2LINES,
|
||||
@ -45,24 +120,3 @@ const SPIDevice sd_slow_spi = {
|
||||
.CRCLength = SPI_CRC_LENGTH_DATASIZE,
|
||||
.NSSPMode = SPI_NSS_PULSE_ENABLE,
|
||||
}};
|
||||
|
||||
/**
|
||||
* Display
|
||||
*/
|
||||
const SPIDevice display_spi = {
|
||||
.spi = &SPI_D,
|
||||
.config = {
|
||||
.Mode = SPI_MODE_MASTER,
|
||||
.Direction = SPI_DIRECTION_2LINES,
|
||||
.DataSize = SPI_DATASIZE_8BIT,
|
||||
.CLKPolarity = SPI_POLARITY_LOW,
|
||||
.CLKPhase = SPI_PHASE_1EDGE,
|
||||
.NSS = SPI_NSS_SOFT,
|
||||
.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16,
|
||||
.FirstBit = SPI_FIRSTBIT_MSB,
|
||||
.TIMode = SPI_TIMODE_DISABLE,
|
||||
.CRCCalculation = SPI_CRCCALCULATION_DISABLE,
|
||||
.CRCPolynomial = 7,
|
||||
.CRCLength = SPI_CRC_LENGTH_DATASIZE,
|
||||
.NSSPMode = SPI_NSS_PULSE_ENABLE,
|
||||
}};
|
||||
|
@ -1,17 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#include <api-hal-gpio.h>
|
||||
#include <cmsis_os2.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const SPI_InitTypeDef api_hal_spi_config_nfc;
|
||||
extern const SPI_InitTypeDef api_hal_spi_config_subghz;
|
||||
extern const SPI_InitTypeDef api_hal_spi_config_display;
|
||||
|
||||
/** API HAL SPI BUS handler
|
||||
* Structure content may change at some point
|
||||
*/
|
||||
typedef struct {
|
||||
SPI_HandleTypeDef* spi;
|
||||
const SPI_HandleTypeDef* spi;
|
||||
const osMutexId_t* mutex;
|
||||
const GpioPin* miso;
|
||||
const GpioPin* mosi;
|
||||
const GpioPin* clk;
|
||||
} ApiHalSpiBus;
|
||||
|
||||
/** API HAL SPI Device handler
|
||||
* Structure content may change at some point
|
||||
*/
|
||||
typedef struct {
|
||||
const ApiHalSpiBus* bus;
|
||||
const SPI_InitTypeDef* config;
|
||||
const GpioPin* chip_select;
|
||||
} ApiHalSpiDevice;
|
||||
|
||||
/** API HAL SPI Standard Device IDs */
|
||||
typedef enum {
|
||||
ApiHalSpiDeviceIdSubGhz, /** SubGhz: CC1101, non-standard SPI usage */
|
||||
ApiHalSpiDeviceIdDisplay, /** Display: ERC12864, only have MOSI */
|
||||
ApiHalSpiDeviceIdSdCard, /** SDCARD: no default bus config, bus must explicitly be configured */
|
||||
ApiHalSpiDeviceIdNfc, /** NFC: ST25R3916, pretty standard, but RFAL makes it complex */
|
||||
|
||||
ApiHalSpiDeviceIdMax, /** Service Value, do not use */
|
||||
} ApiHalSpiDeviceId;
|
||||
|
||||
/** Api Hal Spi Bus R
|
||||
* CC1101, Nfc
|
||||
*/
|
||||
extern const ApiHalSpiBus spi_r;
|
||||
|
||||
/** Api Hal Spi Bus D
|
||||
* Display, SdCard
|
||||
*/
|
||||
extern const ApiHalSpiBus spi_d;
|
||||
|
||||
/** Api Hal Spi devices */
|
||||
extern const ApiHalSpiDevice api_hal_spi_devices[ApiHalSpiDeviceIdMax];
|
||||
|
||||
typedef struct {
|
||||
const ApiHalSpiBus* bus;
|
||||
const SPI_InitTypeDef config;
|
||||
} SPIDevice;
|
||||
|
||||
extern const SPIDevice sd_fast_spi;
|
||||
extern const SPIDevice sd_slow_spi;
|
||||
extern const SPIDevice display_spi;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -1,36 +1,167 @@
|
||||
#include "api-hal-spi.h"
|
||||
#include <cmsis_os2.h>
|
||||
#include <api-hal-resources.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <spi.h>
|
||||
#include <furi.h>
|
||||
|
||||
osMutexId_t spi_mutex_r;
|
||||
osMutexId_t spi_mutex_d;
|
||||
|
||||
extern SPI_HandleTypeDef SPI_R;
|
||||
extern SPI_HandleTypeDef SPI_D;
|
||||
extern void Enable_SPI(SPI_HandleTypeDef* spi);
|
||||
|
||||
void api_hal_spi_init() {
|
||||
spi_mutex_r = osMutexNew(NULL);
|
||||
spi_mutex_d = osMutexNew(NULL);
|
||||
// Spi structure is const, but mutex is not
|
||||
// Need some hell-ish casting to make it work
|
||||
*(osMutexId_t*)spi_r.mutex = osMutexNew(NULL);
|
||||
*(osMutexId_t*)spi_d.mutex = osMutexNew(NULL);
|
||||
//
|
||||
for (size_t i=0; i<ApiHalSpiDeviceIdMax; ++i) {
|
||||
hal_gpio_init(
|
||||
api_hal_spi_devices[i].chip_select,
|
||||
GpioModeOutputPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void api_hal_spi_bus_lock(const ApiHalSpiBus* bus) {
|
||||
furi_assert(bus);
|
||||
if (bus->mutex) {
|
||||
osMutexAcquire(*bus->mutex, osWaitForever);
|
||||
}
|
||||
}
|
||||
|
||||
void api_hal_spi_bus_unlock(const ApiHalSpiBus* bus) {
|
||||
furi_assert(bus);
|
||||
if (bus->mutex) {
|
||||
osMutexRelease(*bus->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
bool api_hal_spi_bus_rx(const ApiHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) {
|
||||
furi_assert(bus);
|
||||
furi_assert(buffer);
|
||||
furi_assert(size > 0);
|
||||
|
||||
HAL_StatusTypeDef ret = HAL_SPI_Receive((SPI_HandleTypeDef *)bus->spi, buffer, size, HAL_MAX_DELAY);
|
||||
|
||||
return ret == HAL_OK;
|
||||
}
|
||||
|
||||
bool api_hal_spi_bus_tx(const ApiHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) {
|
||||
furi_assert(bus);
|
||||
furi_assert(buffer);
|
||||
furi_assert(size > 0);
|
||||
|
||||
HAL_StatusTypeDef ret = HAL_SPI_Transmit((SPI_HandleTypeDef *)bus->spi, buffer, size, HAL_MAX_DELAY);
|
||||
|
||||
return ret == HAL_OK;
|
||||
}
|
||||
|
||||
bool api_hal_spi_bus_trx(const ApiHalSpiBus* bus, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) {
|
||||
furi_assert(bus);
|
||||
furi_assert(tx_buffer);
|
||||
furi_assert(rx_buffer);
|
||||
furi_assert(size > 0);
|
||||
|
||||
HAL_StatusTypeDef ret = HAL_SPI_TransmitReceive((SPI_HandleTypeDef *)bus->spi, tx_buffer, rx_buffer, size, HAL_MAX_DELAY);
|
||||
|
||||
return ret == HAL_OK;
|
||||
}
|
||||
|
||||
const ApiHalSpiDevice* api_hal_spi_device_get(ApiHalSpiDeviceId device_id) {
|
||||
furi_assert(device_id < ApiHalSpiDeviceIdMax);
|
||||
|
||||
const ApiHalSpiDevice* device = &api_hal_spi_devices[device_id];
|
||||
assert(device);
|
||||
api_hal_spi_bus_lock(device->bus);
|
||||
|
||||
if (device->config) {
|
||||
memcpy((SPI_InitTypeDef*)&device->bus->spi->Init, device->config, sizeof(SPI_InitTypeDef));
|
||||
if(HAL_SPI_Init((SPI_HandleTypeDef *)device->bus->spi) != HAL_OK) {
|
||||
Error_Handler();
|
||||
}
|
||||
Enable_SPI((SPI_HandleTypeDef *)device->bus->spi);
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
void api_hal_spi_device_return(const ApiHalSpiDevice* device) {
|
||||
api_hal_spi_bus_unlock(device->bus);
|
||||
}
|
||||
|
||||
bool api_hal_spi_device_rx(const ApiHalSpiDevice* device, uint8_t* buffer, size_t size, uint32_t timeout) {
|
||||
furi_assert(device);
|
||||
furi_assert(buffer);
|
||||
furi_assert(size > 0);
|
||||
|
||||
if (device->chip_select) {
|
||||
hal_gpio_write(device->chip_select, false);
|
||||
}
|
||||
|
||||
bool ret = api_hal_spi_bus_rx(device->bus, buffer, size, HAL_MAX_DELAY);
|
||||
|
||||
if (device->chip_select) {
|
||||
hal_gpio_write(device->chip_select, true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool api_hal_spi_device_tx(const ApiHalSpiDevice* device, uint8_t* buffer, size_t size, uint32_t timeout) {
|
||||
furi_assert(device);
|
||||
furi_assert(buffer);
|
||||
furi_assert(size > 0);
|
||||
|
||||
if (device->chip_select) {
|
||||
hal_gpio_write(device->chip_select, false);
|
||||
}
|
||||
|
||||
bool ret = api_hal_spi_bus_tx(device->bus, buffer, size, HAL_MAX_DELAY);
|
||||
|
||||
if (device->chip_select) {
|
||||
hal_gpio_write(device->chip_select, true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool api_hal_spi_device_trx(const ApiHalSpiDevice* device, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) {
|
||||
furi_assert(device);
|
||||
furi_assert(tx_buffer);
|
||||
furi_assert(rx_buffer);
|
||||
furi_assert(size > 0);
|
||||
|
||||
if (device->chip_select) {
|
||||
hal_gpio_write(device->chip_select, false);
|
||||
}
|
||||
|
||||
bool ret = api_hal_spi_bus_trx(device->bus, tx_buffer, rx_buffer, size, HAL_MAX_DELAY);
|
||||
|
||||
if (device->chip_select) {
|
||||
hal_gpio_write(device->chip_select, true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void api_hal_spi_apply_config(const SPIDevice* device) {
|
||||
osKernelLock();
|
||||
|
||||
memcpy(&device->spi->Init, &device->config, sizeof(SPI_InitTypeDef));
|
||||
memcpy((SPI_InitTypeDef*)&device->bus->spi->Init, &device->config, sizeof(SPI_InitTypeDef));
|
||||
|
||||
if(HAL_SPI_Init(device->spi) != HAL_OK) {
|
||||
if(HAL_SPI_Init((SPI_HandleTypeDef*)device->bus->spi) != HAL_OK) {
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
Enable_SPI(device->spi);
|
||||
Enable_SPI((SPI_HandleTypeDef*)device->bus->spi);
|
||||
|
||||
osKernelUnlock();
|
||||
}
|
||||
|
||||
bool api_hal_spi_config_are_actual(const SPIDevice* device) {
|
||||
return (memcmp(&device->config, &device->spi->Init, sizeof(SPI_InitTypeDef)) == 0);
|
||||
return (memcmp(&device->config, &device->bus->spi->Init, sizeof(SPI_InitTypeDef)) == 0);
|
||||
}
|
||||
|
||||
void api_hal_spi_config_device(const SPIDevice* device) {
|
||||
@ -39,31 +170,11 @@ void api_hal_spi_config_device(const SPIDevice* device) {
|
||||
}
|
||||
}
|
||||
|
||||
void api_hal_spi_lock(SPI_HandleTypeDef* spi) {
|
||||
if(spi == &SPI_D) {
|
||||
osMutexAcquire(spi_mutex_d, osWaitForever);
|
||||
} else if(spi == &SPI_R) {
|
||||
osMutexAcquire(spi_mutex_r, osWaitForever);
|
||||
} else {
|
||||
Error_Handler();
|
||||
}
|
||||
}
|
||||
|
||||
void api_hal_spi_unlock(SPI_HandleTypeDef* spi) {
|
||||
if(spi == &SPI_D) {
|
||||
osMutexRelease(spi_mutex_d);
|
||||
} else if(spi == &SPI_R) {
|
||||
osMutexRelease(spi_mutex_r);
|
||||
} else {
|
||||
Error_Handler();
|
||||
}
|
||||
}
|
||||
|
||||
void api_hal_spi_lock_device(const SPIDevice* device) {
|
||||
api_hal_spi_lock(device->spi);
|
||||
api_hal_spi_bus_lock(device->bus);
|
||||
api_hal_spi_config_device(device);
|
||||
}
|
||||
|
||||
void api_hal_spi_unlock_device(const SPIDevice* device) {
|
||||
api_hal_spi_unlock(device->spi);
|
||||
}
|
||||
api_hal_spi_bus_unlock(device->bus);
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
#include "main.h"
|
||||
#include "api-hal-spi-config.h"
|
||||
#include <api-hal-gpio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -11,15 +13,83 @@ extern "C" {
|
||||
*/
|
||||
void api_hal_spi_init();
|
||||
|
||||
/**
|
||||
* Lock SPI bus
|
||||
*/
|
||||
void api_hal_spi_lock(SPI_HandleTypeDef* spi);
|
||||
/* Bus Level API */
|
||||
|
||||
/**
|
||||
* Unlock SPI bus
|
||||
/** Lock SPI bus
|
||||
* Takes bus mutex, if used
|
||||
*/
|
||||
void api_hal_spi_unlock(SPI_HandleTypeDef* spi);
|
||||
void api_hal_spi_bus_lock(const ApiHalSpiBus* bus);
|
||||
|
||||
/** Unlock SPI bus
|
||||
* Releases BUS mutex, if used
|
||||
*/
|
||||
void api_hal_spi_bus_unlock(const ApiHalSpiBus* bus);
|
||||
|
||||
/** SPI Receive
|
||||
* @param bus - spi bus handler
|
||||
* @param buffer - receive buffer
|
||||
* @param size - transaction size
|
||||
* @param timeout - bus operation timeout in ms
|
||||
*/
|
||||
bool api_hal_spi_bus_rx(const ApiHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout);
|
||||
|
||||
/** SPI Transmit
|
||||
* @param bus - spi bus handler
|
||||
* @param buffer - transmit buffer
|
||||
* @param size - transaction size
|
||||
* @param timeout - bus operation timeout in ms
|
||||
*/
|
||||
bool api_hal_spi_bus_tx(const ApiHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout);
|
||||
|
||||
/** SPI Transmit and Receive
|
||||
* @param bus - spi bus handlere
|
||||
* @param tx_buffer - device handle
|
||||
* @param rx_buffer - device handle
|
||||
* @param size - transaction size
|
||||
* @param timeout - bus operation timeout in ms
|
||||
*/
|
||||
bool api_hal_spi_bus_trx(const ApiHalSpiBus* bus, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout);
|
||||
|
||||
/* Device Level API */
|
||||
|
||||
/** Get Device handle
|
||||
* And lock access to the corresponding SPI BUS
|
||||
* @param device_id - device identifier
|
||||
* @return device handle
|
||||
*/
|
||||
const ApiHalSpiDevice* api_hal_spi_device_get(ApiHalSpiDeviceId device_id);
|
||||
|
||||
/** Return Device handle
|
||||
* And unlock access to the corresponding SPI BUS
|
||||
* @param device - device handle
|
||||
*/
|
||||
void api_hal_spi_device_return(const ApiHalSpiDevice* device);
|
||||
|
||||
/** SPI Recieve
|
||||
* @param device - device handle
|
||||
* @param buffer - receive buffer
|
||||
* @param size - transaction size
|
||||
* @param timeout - bus operation timeout in ms
|
||||
*/
|
||||
bool api_hal_spi_device_rx(const ApiHalSpiDevice* device, uint8_t* buffer, size_t size, uint32_t timeout);
|
||||
|
||||
/** SPI Transmit
|
||||
* @param device - device handle
|
||||
* @param buffer - transmit buffer
|
||||
* @param size - transaction size
|
||||
* @param timeout - bus operation timeout in ms
|
||||
*/
|
||||
bool api_hal_spi_device_tx(const ApiHalSpiDevice* device, uint8_t* buffer, size_t size, uint32_t timeout);
|
||||
|
||||
/** SPI Transmit and Receive
|
||||
* @param device - device handle
|
||||
* @param tx_buffer - device handle
|
||||
* @param rx_buffer - device handle
|
||||
* @param size - transaction size
|
||||
* @param timeout - bus operation timeout in ms
|
||||
*/
|
||||
bool api_hal_spi_device_trx(const ApiHalSpiDevice* device, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout);
|
||||
|
||||
|
||||
/**
|
||||
* Lock SPI device bus and apply config if needed
|
||||
|
@ -1,5 +1,11 @@
|
||||
#include "api-hal-subghz.h"
|
||||
#include <api-hal-spi.h>
|
||||
#include <cc1101.h>
|
||||
|
||||
void api_hal_rf_band_set(RfBand band) {
|
||||
|
||||
}
|
||||
void api_hal_subghz_init() {
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
cc1101_init(device);
|
||||
api_hal_spi_device_return(device);
|
||||
}
|
||||
|
||||
void api_hal_subghz_band_set(RfBand band) {}
|
@ -8,4 +8,5 @@ void api_hal_init() {
|
||||
api_hal_power_init();
|
||||
api_hal_light_init();
|
||||
api_hal_vibro_init();
|
||||
api_hal_subghz_init();
|
||||
}
|
@ -1,155 +1,103 @@
|
||||
/* USER CODE BEGIN Header */
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file : main.h
|
||||
* @brief : Header for main.c file.
|
||||
* This file contains the common defines of the application.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
|
||||
* All rights reserved.</center></h2>
|
||||
*
|
||||
* This software component is licensed by ST under Ultimate Liberty license
|
||||
* SLA0044, the "License"; You may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at:
|
||||
* www.st.com/SLA0044
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
/* USER CODE END Header */
|
||||
|
||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||
#ifndef __MAIN_H
|
||||
#define __MAIN_H
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32wbxx_hal.h"
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN ET */
|
||||
|
||||
/* USER CODE END ET */
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EC */
|
||||
|
||||
/* USER CODE END EC */
|
||||
|
||||
/* Exported macro ------------------------------------------------------------*/
|
||||
/* USER CODE BEGIN EM */
|
||||
|
||||
/* USER CODE END EM */
|
||||
|
||||
/* Exported functions prototypes ---------------------------------------------*/
|
||||
void Error_Handler(void);
|
||||
|
||||
/* USER CODE BEGIN EFP */
|
||||
|
||||
/* USER CODE END EFP */
|
||||
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
#define BUTTON_BACK_Pin GPIO_PIN_13
|
||||
#define BUTTON_BACK_GPIO_Port GPIOC
|
||||
#define BUTTON_BACK_EXTI_IRQn EXTI15_10_IRQn
|
||||
#define QUARTZ_32MHZ_IN_Pin GPIO_PIN_14
|
||||
#define QUARTZ_32MHZ_IN_GPIO_Port GPIOC
|
||||
#define QUARTZ_32MHZ_OUT_Pin GPIO_PIN_15
|
||||
#define QUARTZ_32MHZ_OUT_GPIO_Port GPIOC
|
||||
#define BUTTON_OK_Pin GPIO_PIN_3
|
||||
#define BUTTON_OK_GPIO_Port GPIOH
|
||||
#define BUTTON_OK_EXTI_IRQn EXTI3_IRQn
|
||||
#define SPEAKER_Pin GPIO_PIN_8
|
||||
#define SPEAKER_GPIO_Port GPIOB
|
||||
#define IR_TX_Pin GPIO_PIN_9
|
||||
#define IR_TX_GPIO_Port GPIOB
|
||||
#define PC0_Pin GPIO_PIN_0
|
||||
#define PC0_GPIO_Port GPIOC
|
||||
#define PC1_Pin GPIO_PIN_1
|
||||
#define PC1_GPIO_Port GPIOC
|
||||
#define SPI_D_MISO_Pin GPIO_PIN_2
|
||||
#define SPI_D_MISO_GPIO_Port GPIOC
|
||||
#define PC3_Pin GPIO_PIN_3
|
||||
#define PC3_GPIO_Port GPIOC
|
||||
#define IR_RX_Pin GPIO_PIN_0
|
||||
#define IR_RX_GPIO_Port GPIOA
|
||||
#define RF_SW_0_Pin GPIO_PIN_1
|
||||
#define RF_SW_0_GPIO_Port GPIOA
|
||||
#define RF_SW_1_Pin GPIO_PIN_2
|
||||
#define RF_SW_1_GPIO_Port GPIOA
|
||||
#define PERIPH_POWER_Pin GPIO_PIN_3
|
||||
#define PERIPH_POWER_GPIO_Port GPIOA
|
||||
#define PA4_Pin GPIO_PIN_4
|
||||
#define PA4_GPIO_Port GPIOA
|
||||
#define SPI_R_SCK_Pin GPIO_PIN_5
|
||||
#define SPI_R_SCK_GPIO_Port GPIOA
|
||||
#define PA6_Pin GPIO_PIN_6
|
||||
#define PA6_GPIO_Port GPIOA
|
||||
#define PA7_Pin GPIO_PIN_7
|
||||
#define PA7_GPIO_Port GPIOA
|
||||
#define RFID_PULL_Pin GPIO_PIN_8
|
||||
#define RFID_PULL_GPIO_Port GPIOA
|
||||
#define RFID_PULL_EXTI_IRQn EXTI9_5_IRQn
|
||||
#define CC1101_G0_Pin GPIO_PIN_4
|
||||
#define CC1101_G0_GPIO_Port GPIOC
|
||||
#define RFID_RF_IN_Pin GPIO_PIN_5
|
||||
#define RFID_RF_IN_GPIO_Port GPIOC
|
||||
#define PB2_Pin GPIO_PIN_2
|
||||
#define PB2_GPIO_Port GPIOB
|
||||
#define BUTTON_UP_Pin GPIO_PIN_10
|
||||
#define BUTTON_UP_GPIO_Port GPIOB
|
||||
#define BUTTON_UP_EXTI_IRQn EXTI15_10_IRQn
|
||||
#define BUTTON_LEFT_Pin GPIO_PIN_11
|
||||
#define BUTTON_LEFT_GPIO_Port GPIOB
|
||||
#define BUTTON_LEFT_EXTI_IRQn EXTI15_10_IRQn
|
||||
#define DISPLAY_RST_Pin GPIO_PIN_0
|
||||
#define DISPLAY_RST_GPIO_Port GPIOB
|
||||
#define BUTTON_DOWN_Pin GPIO_PIN_1
|
||||
#define BUTTON_DOWN_GPIO_Port GPIOB
|
||||
#define BUTTON_BACK_GPIO_Port GPIOC
|
||||
#define BUTTON_BACK_Pin GPIO_PIN_13
|
||||
#define BUTTON_DOWN_EXTI_IRQn EXTI1_IRQn
|
||||
#define NFC_CS_Pin GPIO_PIN_4
|
||||
#define NFC_CS_GPIO_Port GPIOE
|
||||
#define BUTTON_RIGHT_Pin GPIO_PIN_12
|
||||
#define BUTTON_RIGHT_GPIO_Port GPIOB
|
||||
#define BUTTON_DOWN_GPIO_Port GPIOB
|
||||
#define BUTTON_DOWN_Pin GPIO_PIN_1
|
||||
#define BUTTON_LEFT_EXTI_IRQn EXTI15_10_IRQn
|
||||
#define BUTTON_LEFT_GPIO_Port GPIOB
|
||||
#define BUTTON_LEFT_Pin GPIO_PIN_11
|
||||
#define BUTTON_OK_EXTI_IRQn EXTI3_IRQn
|
||||
#define BUTTON_OK_GPIO_Port GPIOH
|
||||
#define BUTTON_OK_Pin GPIO_PIN_3
|
||||
#define BUTTON_RIGHT_EXTI_IRQn EXTI15_10_IRQn
|
||||
#define RFID_OUT_Pin GPIO_PIN_13
|
||||
#define RFID_OUT_GPIO_Port GPIOB
|
||||
#define iBTN_Pin GPIO_PIN_14
|
||||
#define iBTN_GPIO_Port GPIOB
|
||||
#define SPI_D_MOSI_Pin GPIO_PIN_15
|
||||
#define SPI_D_MOSI_GPIO_Port GPIOB
|
||||
#define DISPLAY_DI_Pin GPIO_PIN_6
|
||||
#define DISPLAY_DI_GPIO_Port GPIOC
|
||||
#define SD_CD_Pin GPIO_PIN_15
|
||||
#define SD_CD_GPIO_Port GPIOA
|
||||
#define VIBRO_Pin GPIO_PIN_10
|
||||
#define VIBRO_GPIO_Port GPIOC
|
||||
#define DISPLAY_CS_Pin GPIO_PIN_11
|
||||
#define DISPLAY_CS_GPIO_Port GPIOC
|
||||
#define SD_CS_Pin GPIO_PIN_12
|
||||
#define SD_CS_GPIO_Port GPIOC
|
||||
#define CC1101_CS_Pin GPIO_PIN_0
|
||||
#define BUTTON_RIGHT_GPIO_Port GPIOB
|
||||
#define BUTTON_RIGHT_Pin GPIO_PIN_12
|
||||
#define BUTTON_UP_EXTI_IRQn EXTI15_10_IRQn
|
||||
#define BUTTON_UP_GPIO_Port GPIOB
|
||||
#define BUTTON_UP_Pin GPIO_PIN_10
|
||||
#define CC1101_CS_GPIO_Port GPIOD
|
||||
#define SPI_D_SCK_Pin GPIO_PIN_1
|
||||
#define SPI_D_SCK_GPIO_Port GPIOD
|
||||
#define PB3_Pin GPIO_PIN_3
|
||||
#define CC1101_CS_Pin GPIO_PIN_0
|
||||
#define CC1101_G0_GPIO_Port GPIOC
|
||||
#define CC1101_G0_Pin GPIO_PIN_4
|
||||
#define DISPLAY_CS_GPIO_Port GPIOC
|
||||
#define DISPLAY_CS_Pin GPIO_PIN_11
|
||||
#define DISPLAY_DI_GPIO_Port GPIOC
|
||||
#define DISPLAY_DI_Pin GPIO_PIN_6
|
||||
#define DISPLAY_RST_GPIO_Port GPIOB
|
||||
#define DISPLAY_RST_Pin GPIO_PIN_0
|
||||
#define IR_RX_GPIO_Port GPIOA
|
||||
#define IR_RX_Pin GPIO_PIN_0
|
||||
#define IR_TX_GPIO_Port GPIOB
|
||||
#define IR_TX_Pin GPIO_PIN_9
|
||||
#define NFC_CS_GPIO_Port GPIOE
|
||||
#define NFC_CS_Pin GPIO_PIN_4
|
||||
#define PA4_GPIO_Port GPIOA
|
||||
#define PA4_Pin GPIO_PIN_4
|
||||
#define PA6_GPIO_Port GPIOA
|
||||
#define PA6_Pin GPIO_PIN_6
|
||||
#define PA7_GPIO_Port GPIOA
|
||||
#define PA7_Pin GPIO_PIN_7
|
||||
#define PB2_GPIO_Port GPIOB
|
||||
#define PB2_Pin GPIO_PIN_2
|
||||
#define PB3_GPIO_Port GPIOB
|
||||
#define SPI_R_MISO_Pin GPIO_PIN_4
|
||||
#define SPI_R_MISO_GPIO_Port GPIOB
|
||||
#define SPI_R_MOSI_Pin GPIO_PIN_5
|
||||
#define SPI_R_MOSI_GPIO_Port GPIOB
|
||||
/* USER CODE BEGIN Private defines */
|
||||
#define PB3_Pin GPIO_PIN_3
|
||||
#define PC0_GPIO_Port GPIOC
|
||||
#define PC0_Pin GPIO_PIN_0
|
||||
#define PC1_GPIO_Port GPIOC
|
||||
#define PC1_Pin GPIO_PIN_1
|
||||
#define PC3_GPIO_Port GPIOC
|
||||
#define PC3_Pin GPIO_PIN_3
|
||||
#define PERIPH_POWER_GPIO_Port GPIOA
|
||||
#define PERIPH_POWER_Pin GPIO_PIN_3
|
||||
#define QUARTZ_32MHZ_IN_GPIO_Port GPIOC
|
||||
#define QUARTZ_32MHZ_IN_Pin GPIO_PIN_14
|
||||
#define QUARTZ_32MHZ_OUT_GPIO_Port GPIOC
|
||||
#define QUARTZ_32MHZ_OUT_Pin GPIO_PIN_15
|
||||
#define RFID_OUT_GPIO_Port GPIOB
|
||||
#define RFID_OUT_Pin GPIO_PIN_13
|
||||
#define RFID_PULL_EXTI_IRQn EXTI9_5_IRQn
|
||||
#define RFID_PULL_GPIO_Port GPIOA
|
||||
#define RFID_PULL_Pin GPIO_PIN_8
|
||||
#define RFID_RF_IN_GPIO_Port GPIOC
|
||||
#define RFID_RF_IN_Pin GPIO_PIN_5
|
||||
#define RF_SW_0_GPIO_Port GPIOA
|
||||
#define RF_SW_0_Pin GPIO_PIN_1
|
||||
#define RF_SW_1_GPIO_Port GPIOA
|
||||
#define RF_SW_1_Pin GPIO_PIN_2
|
||||
#define SD_CD_GPIO_Port GPIOA
|
||||
#define SD_CD_Pin GPIO_PIN_15
|
||||
#define SD_CS_GPIO_Port GPIOC
|
||||
#define SD_CS_Pin GPIO_PIN_12
|
||||
#define SPEAKER_GPIO_Port GPIOB
|
||||
#define SPEAKER_Pin GPIO_PIN_8
|
||||
#define VIBRO_GPIO_Port GPIOC
|
||||
#define VIBRO_Pin GPIO_PIN_10
|
||||
#define iBTN_GPIO_Port GPIOB
|
||||
#define iBTN_Pin GPIO_PIN_14
|
||||
|
||||
#define MISO_PIN GpioPin{.port = SPI_R_MISO_GPIO_Port, .pin = SPI_R_MISO_Pin}
|
||||
#define SPI_D_MISO_GPIO_Port GPIOC
|
||||
#define SPI_D_MISO_Pin GPIO_PIN_2
|
||||
#define SPI_D_MOSI_GPIO_Port GPIOB
|
||||
#define SPI_D_MOSI_Pin GPIO_PIN_15
|
||||
#define SPI_D_SCK_GPIO_Port GPIOD
|
||||
#define SPI_D_SCK_Pin GPIO_PIN_1
|
||||
#define SPI_R_MISO_GPIO_Port GPIOB
|
||||
#define SPI_R_MISO_Pin GPIO_PIN_4
|
||||
#define SPI_R_MOSI_GPIO_Port GPIOB
|
||||
#define SPI_R_MOSI_Pin GPIO_PIN_5
|
||||
#define SPI_R_SCK_GPIO_Port GPIOA
|
||||
#define SPI_R_SCK_Pin GPIO_PIN_5
|
||||
|
||||
#define SPI_R hspi1
|
||||
#define SPI_D hspi2
|
||||
@ -182,12 +130,6 @@ extern TIM_HandleTypeDef htim16;
|
||||
#define NFC_IRQ_Pin RFID_PULL_Pin
|
||||
#define NFC_IRQ_GPIO_Port RFID_PULL_GPIO_Port
|
||||
|
||||
/* USER CODE END Private defines */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __MAIN_H */
|
||||
|
||||
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|
||||
|
@ -23,5 +23,6 @@ void delay_us(float microseconds) {
|
||||
void delay(float milliseconds) {
|
||||
uint32_t ticks = milliseconds / (1000.0f / osKernelGetTickFreq());
|
||||
osStatus_t result = osDelay(ticks);
|
||||
(void)result;
|
||||
assert(result == osOK);
|
||||
}
|
@ -20,11 +20,6 @@ void hal_gpio_init(
|
||||
HAL_GPIO_Init(gpio->port, &GPIO_InitStruct);
|
||||
}
|
||||
|
||||
void enable_cc1101_irq() {
|
||||
HAL_NVIC_SetPriority(EXTI4_IRQn, 5, 0);
|
||||
HAL_NVIC_EnableIRQ(EXTI4_IRQn);
|
||||
}
|
||||
|
||||
extern COMP_HandleTypeDef hcomp1;
|
||||
|
||||
bool get_rfid_in_level() {
|
||||
|
@ -24,6 +24,12 @@ typedef enum {
|
||||
GpioModeEventRiseFall = GPIO_MODE_EVT_RISING_FALLING,
|
||||
} GpioMode;
|
||||
|
||||
typedef enum {
|
||||
GpioPullNo = GPIO_NOPULL,
|
||||
GpioPullUp = GPIO_PULLUP,
|
||||
GpioPullDown = GPIO_PULLDOWN,
|
||||
} GpioPull;
|
||||
|
||||
typedef enum {
|
||||
GpioSpeedLow = GPIO_SPEED_FREQ_LOW,
|
||||
GpioSpeedMedium = GPIO_SPEED_FREQ_MEDIUM,
|
||||
@ -31,12 +37,6 @@ typedef enum {
|
||||
GpioSpeedVeryHigh = GPIO_SPEED_FREQ_VERY_HIGH,
|
||||
} GpioSpeed;
|
||||
|
||||
typedef enum {
|
||||
GpioPullNo = GPIO_NOPULL,
|
||||
GpioPullUp = GPIO_PULLUP,
|
||||
GpioPullDown = GPIO_PULLDOWN,
|
||||
} GpioPull;
|
||||
|
||||
typedef struct {
|
||||
GPIO_TypeDef* port;
|
||||
uint16_t pin;
|
||||
|
@ -28,3 +28,17 @@ const size_t input_pins_count = sizeof(input_pins) / sizeof(InputPin);
|
||||
const GpioPin vibro_gpio = {VIBRO_GPIO_Port, VIBRO_Pin};
|
||||
const GpioPin ibutton_gpio = {iBTN_GPIO_Port, iBTN_Pin};
|
||||
const GpioPin cc1101_g0_gpio = {CC1101_G0_GPIO_Port, CC1101_G0_Pin};
|
||||
|
||||
const GpioPin gpio_subghz_cs = { .port=CC1101_CS_GPIO_Port, .pin=CC1101_CS_Pin };
|
||||
const GpioPin gpio_display_cs = { .port=DISPLAY_CS_GPIO_Port, .pin=DISPLAY_CS_Pin };
|
||||
const GpioPin gpio_display_rst = { .port=DISPLAY_RST_GPIO_Port, .pin=DISPLAY_RST_Pin };
|
||||
const GpioPin gpio_display_di = { .port=DISPLAY_DI_GPIO_Port, .pin=DISPLAY_DI_Pin };
|
||||
const GpioPin gpio_sdcard_cs = { .port=SD_CS_GPIO_Port, .pin=SD_CS_Pin };
|
||||
const GpioPin gpio_nfc_cs = { .port=NFC_CS_GPIO_Port, .pin=NFC_CS_Pin };
|
||||
|
||||
const GpioPin gpio_spi_d_miso = { .port=SPI_D_MISO_GPIO_Port, .pin=SPI_D_MISO_Pin };
|
||||
const GpioPin gpio_spi_d_mosi = { .port=SPI_D_MOSI_GPIO_Port, .pin=SPI_D_MOSI_Pin };
|
||||
const GpioPin gpio_spi_d_sck = { .port=SPI_D_SCK_GPIO_Port, .pin=SPI_D_SCK_Pin };
|
||||
const GpioPin gpio_spi_r_miso = { .port=SPI_R_MISO_GPIO_Port, .pin=SPI_R_MISO_Pin };
|
||||
const GpioPin gpio_spi_r_mosi = { .port=SPI_R_MOSI_GPIO_Port, .pin=SPI_R_MOSI_Pin };
|
||||
const GpioPin gpio_spi_r_sck = { .port=SPI_R_SCK_GPIO_Port, .pin=SPI_R_SCK_Pin };
|
||||
|
@ -16,7 +16,7 @@ extern "C" {
|
||||
#define POWER_I2C_SDA_GPIO_Port GPIOA
|
||||
|
||||
#define POWER_I2C I2C1
|
||||
/* Timing register value is computed with the STM32CubeMX Tool,
|
||||
/** Timing register value is computed with the STM32CubeMX Tool,
|
||||
* Fast Mode @100kHz with I2CCLK = 64 MHz,
|
||||
* rise time = 0ns, fall time = 0ns
|
||||
*/
|
||||
@ -57,6 +57,24 @@ extern const GpioPin vibro_gpio;
|
||||
extern const GpioPin ibutton_gpio;
|
||||
extern const GpioPin cc1101_g0_gpio;
|
||||
|
||||
extern const GpioPin gpio_subghz_cs;
|
||||
extern const GpioPin gpio_display_cs;
|
||||
|
||||
extern const GpioPin gpio_subghz_cs;
|
||||
extern const GpioPin gpio_display_cs;
|
||||
extern const GpioPin gpio_display_rst;
|
||||
extern const GpioPin gpio_display_di;
|
||||
extern const GpioPin gpio_sdcard_cs;
|
||||
extern const GpioPin gpio_nfc_cs;
|
||||
|
||||
extern const GpioPin gpio_spi_d_miso;
|
||||
extern const GpioPin gpio_spi_d_mosi;
|
||||
extern const GpioPin gpio_spi_d_sck;
|
||||
extern const GpioPin gpio_spi_r_miso;
|
||||
extern const GpioPin gpio_spi_r_mosi;
|
||||
extern const GpioPin gpio_spi_r_sck;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -1,14 +1,89 @@
|
||||
#include "main.h"
|
||||
#include "api-hal-spi-config.h"
|
||||
#include <api-hal-spi-config.h>
|
||||
#include <api-hal-resources.h>
|
||||
|
||||
extern SPI_HandleTypeDef SPI_R;
|
||||
extern SPI_HandleTypeDef SPI_D;
|
||||
|
||||
const SPI_InitTypeDef api_hal_spi_config_nfc = {
|
||||
.Mode = SPI_MODE_MASTER,
|
||||
.Direction = SPI_DIRECTION_2LINES,
|
||||
.DataSize = SPI_DATASIZE_8BIT,
|
||||
.CLKPolarity = SPI_POLARITY_LOW,
|
||||
.CLKPhase = SPI_PHASE_2EDGE,
|
||||
.NSS = SPI_NSS_SOFT,
|
||||
.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8,
|
||||
.FirstBit = SPI_FIRSTBIT_MSB,
|
||||
.TIMode = SPI_TIMODE_DISABLE,
|
||||
.CRCCalculation = SPI_CRCCALCULATION_DISABLE,
|
||||
.CRCPolynomial = 7,
|
||||
.CRCLength = SPI_CRC_LENGTH_DATASIZE,
|
||||
.NSSPMode = SPI_NSS_PULSE_DISABLE,
|
||||
};
|
||||
|
||||
const SPI_InitTypeDef api_hal_spi_config_subghz = {
|
||||
.Mode = SPI_MODE_MASTER,
|
||||
.Direction = SPI_DIRECTION_2LINES,
|
||||
.DataSize = SPI_DATASIZE_8BIT,
|
||||
.CLKPolarity = SPI_POLARITY_LOW,
|
||||
.CLKPhase = SPI_PHASE_1EDGE,
|
||||
.NSS = SPI_NSS_SOFT,
|
||||
.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8,
|
||||
.FirstBit = SPI_FIRSTBIT_MSB,
|
||||
.TIMode = SPI_TIMODE_DISABLE,
|
||||
.CRCCalculation = SPI_CRCCALCULATION_DISABLE,
|
||||
.CRCPolynomial = 7,
|
||||
.CRCLength = SPI_CRC_LENGTH_DATASIZE,
|
||||
.NSSPMode = SPI_NSS_PULSE_DISABLE,
|
||||
};
|
||||
|
||||
const SPI_InitTypeDef api_hal_spi_config_display = {
|
||||
.Mode = SPI_MODE_MASTER,
|
||||
.Direction = SPI_DIRECTION_2LINES,
|
||||
.DataSize = SPI_DATASIZE_8BIT,
|
||||
.CLKPolarity = SPI_POLARITY_LOW,
|
||||
.CLKPhase = SPI_PHASE_1EDGE,
|
||||
.NSS = SPI_NSS_SOFT,
|
||||
.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16,
|
||||
.FirstBit = SPI_FIRSTBIT_MSB,
|
||||
.TIMode = SPI_TIMODE_DISABLE,
|
||||
.CRCCalculation = SPI_CRCCALCULATION_DISABLE,
|
||||
.CRCPolynomial = 7,
|
||||
.CRCLength = SPI_CRC_LENGTH_DATASIZE,
|
||||
.NSSPMode = SPI_NSS_PULSE_ENABLE,
|
||||
};
|
||||
|
||||
osMutexId_t spi_mutex_d = NULL;
|
||||
osMutexId_t spi_mutex_r = NULL;
|
||||
|
||||
const ApiHalSpiBus spi_r = {
|
||||
.spi=&SPI_R,
|
||||
.mutex=&spi_mutex_r,
|
||||
.miso=&gpio_spi_r_miso,
|
||||
.mosi=&gpio_spi_r_mosi,
|
||||
.clk=&gpio_spi_r_sck,
|
||||
};
|
||||
|
||||
const ApiHalSpiBus spi_d = {
|
||||
.spi=&SPI_D,
|
||||
.mutex=&spi_mutex_d,
|
||||
.miso=&gpio_spi_d_miso,
|
||||
.mosi=&gpio_spi_d_mosi,
|
||||
.clk=&gpio_spi_d_sck,
|
||||
};
|
||||
|
||||
const ApiHalSpiDevice api_hal_spi_devices[ApiHalSpiDeviceIdMax] = {
|
||||
{ .bus=&spi_r, .config=&api_hal_spi_config_subghz, .chip_select=&gpio_subghz_cs, },
|
||||
{ .bus=&spi_d, .config=&api_hal_spi_config_display, .chip_select=&gpio_display_cs, },
|
||||
{ .bus=&spi_d, .config=NULL, .chip_select=&gpio_sdcard_cs, },
|
||||
{ .bus=&spi_r, .config=&api_hal_spi_config_nfc, .chip_select=&gpio_nfc_cs },
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* SD Card in fast mode (after init)
|
||||
*/
|
||||
const SPIDevice sd_fast_spi = {
|
||||
.spi = &SPI_D,
|
||||
.bus= &spi_d,
|
||||
.config = {
|
||||
.Mode = SPI_MODE_MASTER,
|
||||
.Direction = SPI_DIRECTION_2LINES,
|
||||
@ -29,7 +104,7 @@ const SPIDevice sd_fast_spi = {
|
||||
* SD Card in slow mode (before init)
|
||||
*/
|
||||
const SPIDevice sd_slow_spi = {
|
||||
.spi = &SPI_D,
|
||||
.bus= &spi_d,
|
||||
.config = {
|
||||
.Mode = SPI_MODE_MASTER,
|
||||
.Direction = SPI_DIRECTION_2LINES,
|
||||
@ -45,24 +120,3 @@ const SPIDevice sd_slow_spi = {
|
||||
.CRCLength = SPI_CRC_LENGTH_DATASIZE,
|
||||
.NSSPMode = SPI_NSS_PULSE_ENABLE,
|
||||
}};
|
||||
|
||||
/**
|
||||
* Display
|
||||
*/
|
||||
const SPIDevice display_spi = {
|
||||
.spi = &SPI_D,
|
||||
.config = {
|
||||
.Mode = SPI_MODE_MASTER,
|
||||
.Direction = SPI_DIRECTION_2LINES,
|
||||
.DataSize = SPI_DATASIZE_8BIT,
|
||||
.CLKPolarity = SPI_POLARITY_LOW,
|
||||
.CLKPhase = SPI_PHASE_1EDGE,
|
||||
.NSS = SPI_NSS_SOFT,
|
||||
.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16,
|
||||
.FirstBit = SPI_FIRSTBIT_MSB,
|
||||
.TIMode = SPI_TIMODE_DISABLE,
|
||||
.CRCCalculation = SPI_CRCCALCULATION_DISABLE,
|
||||
.CRCPolynomial = 7,
|
||||
.CRCLength = SPI_CRC_LENGTH_DATASIZE,
|
||||
.NSSPMode = SPI_NSS_PULSE_ENABLE,
|
||||
}};
|
||||
|
@ -1,17 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#include <api-hal-gpio.h>
|
||||
#include <cmsis_os2.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const SPI_InitTypeDef api_hal_spi_config_nfc;
|
||||
extern const SPI_InitTypeDef api_hal_spi_config_subghz;
|
||||
extern const SPI_InitTypeDef api_hal_spi_config_display;
|
||||
|
||||
/** API HAL SPI BUS handler
|
||||
* Structure content may change at some point
|
||||
*/
|
||||
typedef struct {
|
||||
SPI_HandleTypeDef* spi;
|
||||
const SPI_HandleTypeDef* spi;
|
||||
const osMutexId_t* mutex;
|
||||
const GpioPin* miso;
|
||||
const GpioPin* mosi;
|
||||
const GpioPin* clk;
|
||||
} ApiHalSpiBus;
|
||||
|
||||
/** API HAL SPI Device handler
|
||||
* Structure content may change at some point
|
||||
*/
|
||||
typedef struct {
|
||||
const ApiHalSpiBus* bus;
|
||||
const SPI_InitTypeDef* config;
|
||||
const GpioPin* chip_select;
|
||||
} ApiHalSpiDevice;
|
||||
|
||||
/** API HAL SPI Standard Device IDs */
|
||||
typedef enum {
|
||||
ApiHalSpiDeviceIdSubGhz, /** SubGhz: CC1101, non-standard SPI usage */
|
||||
ApiHalSpiDeviceIdDisplay, /** Display: ERC12864, only have MOSI */
|
||||
ApiHalSpiDeviceIdSdCard, /** SDCARD: no default bus config, bus must explicitly be configured */
|
||||
ApiHalSpiDeviceIdNfc, /** NFC: ST25R3916, pretty standard, but RFAL makes it complex */
|
||||
|
||||
ApiHalSpiDeviceIdMax, /** Service Value, do not use */
|
||||
} ApiHalSpiDeviceId;
|
||||
|
||||
/** Api Hal Spi Bus R
|
||||
* CC1101, Nfc
|
||||
*/
|
||||
extern const ApiHalSpiBus spi_r;
|
||||
|
||||
/** Api Hal Spi Bus D
|
||||
* Display, SdCard
|
||||
*/
|
||||
extern const ApiHalSpiBus spi_d;
|
||||
|
||||
/** Api Hal Spi devices */
|
||||
extern const ApiHalSpiDevice api_hal_spi_devices[ApiHalSpiDeviceIdMax];
|
||||
|
||||
typedef struct {
|
||||
const ApiHalSpiBus* bus;
|
||||
const SPI_InitTypeDef config;
|
||||
} SPIDevice;
|
||||
|
||||
extern const SPIDevice sd_fast_spi;
|
||||
extern const SPIDevice sd_slow_spi;
|
||||
extern const SPIDevice display_spi;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -1,36 +1,167 @@
|
||||
#include "api-hal-spi.h"
|
||||
#include <cmsis_os2.h>
|
||||
#include <api-hal-resources.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <spi.h>
|
||||
#include <furi.h>
|
||||
|
||||
osMutexId_t spi_mutex_r;
|
||||
osMutexId_t spi_mutex_d;
|
||||
|
||||
extern SPI_HandleTypeDef SPI_R;
|
||||
extern SPI_HandleTypeDef SPI_D;
|
||||
extern void Enable_SPI(SPI_HandleTypeDef* spi);
|
||||
|
||||
void api_hal_spi_init() {
|
||||
spi_mutex_r = osMutexNew(NULL);
|
||||
spi_mutex_d = osMutexNew(NULL);
|
||||
// Spi structure is const, but mutex is not
|
||||
// Need some hell-ish casting to make it work
|
||||
*(osMutexId_t*)spi_r.mutex = osMutexNew(NULL);
|
||||
*(osMutexId_t*)spi_d.mutex = osMutexNew(NULL);
|
||||
//
|
||||
for (size_t i=0; i<ApiHalSpiDeviceIdMax; ++i) {
|
||||
hal_gpio_init(
|
||||
api_hal_spi_devices[i].chip_select,
|
||||
GpioModeOutputPushPull,
|
||||
GpioPullNo,
|
||||
GpioSpeedVeryHigh
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void api_hal_spi_bus_lock(const ApiHalSpiBus* bus) {
|
||||
furi_assert(bus);
|
||||
if (bus->mutex) {
|
||||
osMutexAcquire(*bus->mutex, osWaitForever);
|
||||
}
|
||||
}
|
||||
|
||||
void api_hal_spi_bus_unlock(const ApiHalSpiBus* bus) {
|
||||
furi_assert(bus);
|
||||
if (bus->mutex) {
|
||||
osMutexRelease(*bus->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
bool api_hal_spi_bus_rx(const ApiHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) {
|
||||
furi_assert(bus);
|
||||
furi_assert(buffer);
|
||||
furi_assert(size > 0);
|
||||
|
||||
HAL_StatusTypeDef ret = HAL_SPI_Receive((SPI_HandleTypeDef *)bus->spi, buffer, size, HAL_MAX_DELAY);
|
||||
|
||||
return ret == HAL_OK;
|
||||
}
|
||||
|
||||
bool api_hal_spi_bus_tx(const ApiHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout) {
|
||||
furi_assert(bus);
|
||||
furi_assert(buffer);
|
||||
furi_assert(size > 0);
|
||||
|
||||
HAL_StatusTypeDef ret = HAL_SPI_Transmit((SPI_HandleTypeDef *)bus->spi, buffer, size, HAL_MAX_DELAY);
|
||||
|
||||
return ret == HAL_OK;
|
||||
}
|
||||
|
||||
bool api_hal_spi_bus_trx(const ApiHalSpiBus* bus, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) {
|
||||
furi_assert(bus);
|
||||
furi_assert(tx_buffer);
|
||||
furi_assert(rx_buffer);
|
||||
furi_assert(size > 0);
|
||||
|
||||
HAL_StatusTypeDef ret = HAL_SPI_TransmitReceive((SPI_HandleTypeDef *)bus->spi, tx_buffer, rx_buffer, size, HAL_MAX_DELAY);
|
||||
|
||||
return ret == HAL_OK;
|
||||
}
|
||||
|
||||
const ApiHalSpiDevice* api_hal_spi_device_get(ApiHalSpiDeviceId device_id) {
|
||||
furi_assert(device_id < ApiHalSpiDeviceIdMax);
|
||||
|
||||
const ApiHalSpiDevice* device = &api_hal_spi_devices[device_id];
|
||||
assert(device);
|
||||
api_hal_spi_bus_lock(device->bus);
|
||||
|
||||
if (device->config) {
|
||||
memcpy((SPI_InitTypeDef*)&device->bus->spi->Init, device->config, sizeof(SPI_InitTypeDef));
|
||||
if(HAL_SPI_Init((SPI_HandleTypeDef *)device->bus->spi) != HAL_OK) {
|
||||
Error_Handler();
|
||||
}
|
||||
Enable_SPI((SPI_HandleTypeDef *)device->bus->spi);
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
void api_hal_spi_device_return(const ApiHalSpiDevice* device) {
|
||||
api_hal_spi_bus_unlock(device->bus);
|
||||
}
|
||||
|
||||
bool api_hal_spi_device_rx(const ApiHalSpiDevice* device, uint8_t* buffer, size_t size, uint32_t timeout) {
|
||||
furi_assert(device);
|
||||
furi_assert(buffer);
|
||||
furi_assert(size > 0);
|
||||
|
||||
if (device->chip_select) {
|
||||
hal_gpio_write(device->chip_select, false);
|
||||
}
|
||||
|
||||
bool ret = api_hal_spi_bus_rx(device->bus, buffer, size, HAL_MAX_DELAY);
|
||||
|
||||
if (device->chip_select) {
|
||||
hal_gpio_write(device->chip_select, true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool api_hal_spi_device_tx(const ApiHalSpiDevice* device, uint8_t* buffer, size_t size, uint32_t timeout) {
|
||||
furi_assert(device);
|
||||
furi_assert(buffer);
|
||||
furi_assert(size > 0);
|
||||
|
||||
if (device->chip_select) {
|
||||
hal_gpio_write(device->chip_select, false);
|
||||
}
|
||||
|
||||
bool ret = api_hal_spi_bus_tx(device->bus, buffer, size, HAL_MAX_DELAY);
|
||||
|
||||
if (device->chip_select) {
|
||||
hal_gpio_write(device->chip_select, true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool api_hal_spi_device_trx(const ApiHalSpiDevice* device, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout) {
|
||||
furi_assert(device);
|
||||
furi_assert(tx_buffer);
|
||||
furi_assert(rx_buffer);
|
||||
furi_assert(size > 0);
|
||||
|
||||
if (device->chip_select) {
|
||||
hal_gpio_write(device->chip_select, false);
|
||||
}
|
||||
|
||||
bool ret = api_hal_spi_bus_trx(device->bus, tx_buffer, rx_buffer, size, HAL_MAX_DELAY);
|
||||
|
||||
if (device->chip_select) {
|
||||
hal_gpio_write(device->chip_select, true);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void api_hal_spi_apply_config(const SPIDevice* device) {
|
||||
osKernelLock();
|
||||
|
||||
memcpy(&device->spi->Init, &device->config, sizeof(SPI_InitTypeDef));
|
||||
memcpy((SPI_InitTypeDef*)&device->bus->spi->Init, &device->config, sizeof(SPI_InitTypeDef));
|
||||
|
||||
if(HAL_SPI_Init(device->spi) != HAL_OK) {
|
||||
if(HAL_SPI_Init((SPI_HandleTypeDef*)device->bus->spi) != HAL_OK) {
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
Enable_SPI(device->spi);
|
||||
Enable_SPI((SPI_HandleTypeDef*)device->bus->spi);
|
||||
|
||||
osKernelUnlock();
|
||||
}
|
||||
|
||||
bool api_hal_spi_config_are_actual(const SPIDevice* device) {
|
||||
return (memcmp(&device->config, &device->spi->Init, sizeof(SPI_InitTypeDef)) == 0);
|
||||
return (memcmp(&device->config, &device->bus->spi->Init, sizeof(SPI_InitTypeDef)) == 0);
|
||||
}
|
||||
|
||||
void api_hal_spi_config_device(const SPIDevice* device) {
|
||||
@ -39,31 +170,11 @@ void api_hal_spi_config_device(const SPIDevice* device) {
|
||||
}
|
||||
}
|
||||
|
||||
void api_hal_spi_lock(SPI_HandleTypeDef* spi) {
|
||||
if(spi == &SPI_D) {
|
||||
osMutexAcquire(spi_mutex_d, osWaitForever);
|
||||
} else if(spi == &SPI_R) {
|
||||
osMutexAcquire(spi_mutex_r, osWaitForever);
|
||||
} else {
|
||||
Error_Handler();
|
||||
}
|
||||
}
|
||||
|
||||
void api_hal_spi_unlock(SPI_HandleTypeDef* spi) {
|
||||
if(spi == &SPI_D) {
|
||||
osMutexRelease(spi_mutex_d);
|
||||
} else if(spi == &SPI_R) {
|
||||
osMutexRelease(spi_mutex_r);
|
||||
} else {
|
||||
Error_Handler();
|
||||
}
|
||||
}
|
||||
|
||||
void api_hal_spi_lock_device(const SPIDevice* device) {
|
||||
api_hal_spi_lock(device->spi);
|
||||
api_hal_spi_bus_lock(device->bus);
|
||||
api_hal_spi_config_device(device);
|
||||
}
|
||||
|
||||
void api_hal_spi_unlock_device(const SPIDevice* device) {
|
||||
api_hal_spi_unlock(device->spi);
|
||||
}
|
||||
api_hal_spi_bus_unlock(device->bus);
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
#include "main.h"
|
||||
#include "api-hal-spi-config.h"
|
||||
#include <api-hal-gpio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -11,15 +13,83 @@ extern "C" {
|
||||
*/
|
||||
void api_hal_spi_init();
|
||||
|
||||
/**
|
||||
* Lock SPI bus
|
||||
*/
|
||||
void api_hal_spi_lock(SPI_HandleTypeDef* spi);
|
||||
/* Bus Level API */
|
||||
|
||||
/**
|
||||
* Unlock SPI bus
|
||||
/** Lock SPI bus
|
||||
* Takes bus mutex, if used
|
||||
*/
|
||||
void api_hal_spi_unlock(SPI_HandleTypeDef* spi);
|
||||
void api_hal_spi_bus_lock(const ApiHalSpiBus* bus);
|
||||
|
||||
/** Unlock SPI bus
|
||||
* Releases BUS mutex, if used
|
||||
*/
|
||||
void api_hal_spi_bus_unlock(const ApiHalSpiBus* bus);
|
||||
|
||||
/** SPI Receive
|
||||
* @param bus - spi bus handler
|
||||
* @param buffer - receive buffer
|
||||
* @param size - transaction size
|
||||
* @param timeout - bus operation timeout in ms
|
||||
*/
|
||||
bool api_hal_spi_bus_rx(const ApiHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout);
|
||||
|
||||
/** SPI Transmit
|
||||
* @param bus - spi bus handler
|
||||
* @param buffer - transmit buffer
|
||||
* @param size - transaction size
|
||||
* @param timeout - bus operation timeout in ms
|
||||
*/
|
||||
bool api_hal_spi_bus_tx(const ApiHalSpiBus* bus, uint8_t* buffer, size_t size, uint32_t timeout);
|
||||
|
||||
/** SPI Transmit and Receive
|
||||
* @param bus - spi bus handlere
|
||||
* @param tx_buffer - device handle
|
||||
* @param rx_buffer - device handle
|
||||
* @param size - transaction size
|
||||
* @param timeout - bus operation timeout in ms
|
||||
*/
|
||||
bool api_hal_spi_bus_trx(const ApiHalSpiBus* bus, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout);
|
||||
|
||||
/* Device Level API */
|
||||
|
||||
/** Get Device handle
|
||||
* And lock access to the corresponding SPI BUS
|
||||
* @param device_id - device identifier
|
||||
* @return device handle
|
||||
*/
|
||||
const ApiHalSpiDevice* api_hal_spi_device_get(ApiHalSpiDeviceId device_id);
|
||||
|
||||
/** Return Device handle
|
||||
* And unlock access to the corresponding SPI BUS
|
||||
* @param device - device handle
|
||||
*/
|
||||
void api_hal_spi_device_return(const ApiHalSpiDevice* device);
|
||||
|
||||
/** SPI Recieve
|
||||
* @param device - device handle
|
||||
* @param buffer - receive buffer
|
||||
* @param size - transaction size
|
||||
* @param timeout - bus operation timeout in ms
|
||||
*/
|
||||
bool api_hal_spi_device_rx(const ApiHalSpiDevice* device, uint8_t* buffer, size_t size, uint32_t timeout);
|
||||
|
||||
/** SPI Transmit
|
||||
* @param device - device handle
|
||||
* @param buffer - transmit buffer
|
||||
* @param size - transaction size
|
||||
* @param timeout - bus operation timeout in ms
|
||||
*/
|
||||
bool api_hal_spi_device_tx(const ApiHalSpiDevice* device, uint8_t* buffer, size_t size, uint32_t timeout);
|
||||
|
||||
/** SPI Transmit and Receive
|
||||
* @param device - device handle
|
||||
* @param tx_buffer - device handle
|
||||
* @param rx_buffer - device handle
|
||||
* @param size - transaction size
|
||||
* @param timeout - bus operation timeout in ms
|
||||
*/
|
||||
bool api_hal_spi_device_trx(const ApiHalSpiDevice* device, uint8_t* tx_buffer, uint8_t* rx_buffer, size_t size, uint32_t timeout);
|
||||
|
||||
|
||||
/**
|
||||
* Lock SPI device bus and apply config if needed
|
||||
|
@ -1,19 +1,181 @@
|
||||
#include "api-hal-subghz.h"
|
||||
#include <stm32wbxx_ll_gpio.h>
|
||||
#include <api-hal-gpio.h>
|
||||
#include <api-hal-spi.h>
|
||||
#include <cc1101.h>
|
||||
#include <stdio.h>
|
||||
#include "main.h"
|
||||
|
||||
void api_hal_rf_band_set(RfBand band) {
|
||||
if (band == RfBand1) {
|
||||
LL_GPIO_ResetOutputPin(RF_SW_0_GPIO_Port, RF_SW_0_Pin);
|
||||
LL_GPIO_SetOutputPin(RF_SW_1_GPIO_Port, RF_SW_1_Pin);
|
||||
} else if (band == RfBand2) {
|
||||
LL_GPIO_SetOutputPin(RF_SW_0_GPIO_Port, RF_SW_0_Pin);
|
||||
LL_GPIO_ResetOutputPin(RF_SW_1_GPIO_Port, RF_SW_1_Pin);
|
||||
} else if (band == RfBand3) {
|
||||
LL_GPIO_SetOutputPin(RF_SW_0_GPIO_Port, RF_SW_0_Pin);
|
||||
LL_GPIO_SetOutputPin(RF_SW_1_GPIO_Port, RF_SW_1_Pin);
|
||||
} else if (band == RfBandIsolation) {
|
||||
LL_GPIO_ResetOutputPin(RF_SW_0_GPIO_Port, RF_SW_0_Pin);
|
||||
LL_GPIO_ResetOutputPin(RF_SW_1_GPIO_Port, RF_SW_1_Pin);
|
||||
static const uint8_t api_hal_subghz_preset_ook_async_regs[][2] = {
|
||||
/* Base setting */
|
||||
{ CC1101_IOCFG0, 0x0D }, // GD0 as async serial data output/input
|
||||
{ CC1101_FSCTRL1, 0x06 }, // Set IF 26m/2^10*2=2.2MHz
|
||||
{ CC1101_MCSM0, 0x18 }, // Autocalibrate on idle to TRX, ~150us OSC guard time
|
||||
/* Async OOK Specific things */
|
||||
{ CC1101_MDMCFG2, 0x30 }, // ASK/OOK, No preamble/sync
|
||||
{ CC1101_PKTCTRL0, 0x32 }, // Async, no CRC, Infinite
|
||||
{ CC1101_FREND0, 0x01 }, // OOK/ASK PATABLE
|
||||
/* End */
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
static const uint8_t api_hal_subghz_preset_ook_async_patable[8] = {
|
||||
0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static const uint8_t api_hal_subghz_preset_2fsk_packet_regs[][2] = {
|
||||
/* Base setting */
|
||||
{ CC1101_IOCFG0, 0x06 }, // GD0 as async serial data output/input
|
||||
{ CC1101_FSCTRL1, 0x06 }, // Set IF 26m/2^10*2=2.2MHz
|
||||
{ CC1101_MCSM0, 0x18 }, // Autocalibrate on idle to TRX, ~150us OSC guard time
|
||||
/* End */
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
static const uint8_t api_hal_subghz_preset_2fsk_packet_patable[8] = {
|
||||
0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
void api_hal_subghz_init() {
|
||||
LL_GPIO_SetPinMode(RF_SW_0_GPIO_Port, RF_SW_0_Pin, LL_GPIO_MODE_OUTPUT);
|
||||
LL_GPIO_SetPinSpeed(RF_SW_0_GPIO_Port, RF_SW_0_Pin, LL_GPIO_SPEED_FREQ_LOW);
|
||||
LL_GPIO_SetPinOutputType(RF_SW_0_GPIO_Port, RF_SW_0_Pin, LL_GPIO_OUTPUT_PUSHPULL);
|
||||
LL_GPIO_SetPinMode(RF_SW_1_GPIO_Port, RF_SW_1_Pin, LL_GPIO_MODE_OUTPUT);
|
||||
LL_GPIO_SetPinSpeed(RF_SW_1_GPIO_Port, RF_SW_1_Pin, LL_GPIO_SPEED_FREQ_LOW);
|
||||
LL_GPIO_SetPinOutputType(RF_SW_1_GPIO_Port, RF_SW_1_Pin, LL_GPIO_OUTPUT_PUSHPULL);
|
||||
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
// Reset and shutdown
|
||||
cc1101_reset(device);
|
||||
cc1101_write_reg(device, CC1101_IOCFG0, 0x2E); // High impedance 3-state
|
||||
cc1101_shutdown(device);
|
||||
api_hal_spi_device_return(device);
|
||||
}
|
||||
|
||||
void api_hal_subghz_dump_state() {
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
printf(
|
||||
"[api_hal_subghz] cc1101 chip %d, version %d\r\n",
|
||||
cc1101_get_partnumber(device),
|
||||
cc1101_get_version(device)
|
||||
);
|
||||
api_hal_spi_device_return(device);
|
||||
}
|
||||
|
||||
void api_hal_subghz_load_preset(ApiHalSubGhzPreset preset) {
|
||||
if(preset == ApiHalSubGhzPresetOokAsync) {
|
||||
api_hal_subghz_load_registers(api_hal_subghz_preset_ook_async_regs);
|
||||
api_hal_subghz_load_patable(api_hal_subghz_preset_ook_async_patable);
|
||||
} else if(preset == ApiHalSubGhzPreset2FskPacket) {
|
||||
api_hal_subghz_load_registers(api_hal_subghz_preset_2fsk_packet_regs);
|
||||
api_hal_subghz_load_patable(api_hal_subghz_preset_2fsk_packet_patable);
|
||||
}
|
||||
}
|
||||
|
||||
void api_hal_subghz_load_registers(const uint8_t data[][2]) {
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
cc1101_reset(device);
|
||||
uint32_t i = 0;
|
||||
while (data[i][0]) {
|
||||
cc1101_write_reg(device, data[i][0], data[i][1]);
|
||||
i++;
|
||||
}
|
||||
api_hal_spi_device_return(device);
|
||||
}
|
||||
|
||||
void api_hal_subghz_load_patable(const uint8_t data[8]) {
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
cc1101_set_pa_table(device, data);
|
||||
api_hal_spi_device_return(device);
|
||||
}
|
||||
|
||||
void api_hal_subghz_write_packet(const uint8_t* data, uint8_t size) {
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
cc1101_flush_tx(device);
|
||||
cc1101_write_fifo(device, data, size);
|
||||
api_hal_spi_device_return(device);
|
||||
}
|
||||
|
||||
void api_hal_subghz_read_packet(uint8_t* data, uint8_t size) {
|
||||
|
||||
}
|
||||
|
||||
void api_hal_subghz_shutdown() {
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
// Reset and shutdown
|
||||
cc1101_shutdown(device);
|
||||
api_hal_spi_device_return(device);
|
||||
}
|
||||
|
||||
void api_hal_subghz_reset() {
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
cc1101_reset(device);
|
||||
api_hal_spi_device_return(device);
|
||||
}
|
||||
|
||||
void api_hal_subghz_idle() {
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
cc1101_switch_to_idle(device);
|
||||
api_hal_spi_device_return(device);
|
||||
}
|
||||
|
||||
void api_hal_subghz_rx() {
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
cc1101_switch_to_rx(device);
|
||||
api_hal_spi_device_return(device);
|
||||
}
|
||||
|
||||
void api_hal_subghz_tx() {
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
cc1101_switch_to_tx(device);
|
||||
api_hal_spi_device_return(device);
|
||||
}
|
||||
|
||||
float api_hal_subghz_get_rssi() {
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
int32_t rssi_dec = cc1101_get_rssi(device);
|
||||
api_hal_spi_device_return(device);
|
||||
|
||||
float rssi = rssi_dec;
|
||||
if(rssi_dec >= 128) {
|
||||
rssi = ((rssi - 256.0f) / 2.0f) - 74.0f;
|
||||
} else {
|
||||
rssi = (rssi / 2.0f) - 74.0f;
|
||||
}
|
||||
|
||||
return rssi;
|
||||
}
|
||||
|
||||
uint32_t api_hal_subghz_set_frequency(uint32_t value) {
|
||||
const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz);
|
||||
|
||||
// Compensate rounding
|
||||
if (value % cc1101_get_frequency_step(device) > (cc1101_get_frequency_step(device) / 2)) {
|
||||
value += cc1101_get_frequency_step(device);
|
||||
}
|
||||
|
||||
uint32_t real_frequency = cc1101_set_frequency(device, value);
|
||||
cc1101_calibrate(device);
|
||||
|
||||
api_hal_spi_device_return(device);
|
||||
|
||||
return real_frequency;
|
||||
}
|
||||
|
||||
void api_hal_subghz_set_path(ApiHalSubGhzPath path) {
|
||||
if (path == ApiHalSubGhzPath1) {
|
||||
LL_GPIO_ResetOutputPin(RF_SW_0_GPIO_Port, RF_SW_0_Pin);
|
||||
LL_GPIO_SetOutputPin(RF_SW_1_GPIO_Port, RF_SW_1_Pin);
|
||||
} else if (path == ApiHalSubGhzPath2) {
|
||||
LL_GPIO_SetOutputPin(RF_SW_0_GPIO_Port, RF_SW_0_Pin);
|
||||
LL_GPIO_ResetOutputPin(RF_SW_1_GPIO_Port, RF_SW_1_Pin);
|
||||
} else if (path == ApiHalSubGhzPath3) {
|
||||
LL_GPIO_SetOutputPin(RF_SW_0_GPIO_Port, RF_SW_0_Pin);
|
||||
LL_GPIO_SetOutputPin(RF_SW_1_GPIO_Port, RF_SW_1_Pin);
|
||||
} else if (path == ApiHalSubGhzPathIsolate) {
|
||||
LL_GPIO_ResetOutputPin(RF_SW_0_GPIO_Port, RF_SW_0_Pin);
|
||||
LL_GPIO_ResetOutputPin(RF_SW_1_GPIO_Port, RF_SW_1_Pin);
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -8,4 +8,5 @@ void api_hal_init() {
|
||||
api_hal_power_init();
|
||||
api_hal_light_init();
|
||||
api_hal_vibro_init();
|
||||
api_hal_subghz_init();
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
static osThreadAttr_t platform_irq_thread_attr;
|
||||
static volatile osThreadId_t platform_irq_thread_id = NULL;
|
||||
static volatile PlatformIrqCallback platform_irq_callback = NULL;
|
||||
static ApiHalSpiDevice* platform_st25r3916 = NULL;
|
||||
|
||||
void nfc_isr(void* _pin, void* _ctx) {
|
||||
uint32_t pin = (uint32_t)_pin;
|
||||
@ -36,27 +37,30 @@ void platformSetIrqCallback(PlatformIrqCallback callback) {
|
||||
}
|
||||
|
||||
HAL_StatusTypeDef platformSpiTxRx(const uint8_t *txBuf, uint8_t *rxBuf, uint16_t len) {
|
||||
HAL_StatusTypeDef ret;
|
||||
bool ret = false;
|
||||
if (txBuf && rxBuf) {
|
||||
ret = HAL_SPI_TransmitReceive(&SPI_R, (uint8_t*)txBuf, rxBuf, len, HAL_MAX_DELAY);
|
||||
ret = api_hal_spi_bus_trx(platform_st25r3916->bus, (uint8_t*)txBuf, rxBuf, len, 1000);
|
||||
} else if (txBuf) {
|
||||
ret = HAL_SPI_Transmit(&SPI_R, (uint8_t*)txBuf, len, HAL_MAX_DELAY);
|
||||
ret = api_hal_spi_bus_tx(platform_st25r3916->bus, (uint8_t*)txBuf, len, 1000);
|
||||
} else if (rxBuf) {
|
||||
ret = HAL_SPI_Receive(&SPI_R, (uint8_t*)rxBuf, len, HAL_MAX_DELAY);
|
||||
ret = api_hal_spi_bus_rx(platform_st25r3916->bus, (uint8_t*)rxBuf, len, 1000);
|
||||
}
|
||||
|
||||
if(ret != HAL_OK) {
|
||||
|
||||
if(!ret) {
|
||||
asm("bkpt 1");
|
||||
exit(255);
|
||||
return HAL_ERROR;
|
||||
} else {
|
||||
return HAL_OK;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void platformProtectST25RComm() {
|
||||
api_hal_spi_lock(&SPI_R);
|
||||
NFC_SPI_Reconfigure();
|
||||
furi_assert(platform_st25r3916 == NULL);
|
||||
platform_st25r3916 = (ApiHalSpiDevice*)api_hal_spi_device_get(ApiHalSpiDeviceIdNfc);
|
||||
}
|
||||
|
||||
void platformUnprotectST25RComm() {
|
||||
api_hal_spi_unlock(&SPI_R);
|
||||
furi_assert(platform_st25r3916);
|
||||
api_hal_spi_device_return(platform_st25r3916);
|
||||
platform_st25r3916 = NULL;
|
||||
}
|
||||
|
@ -58,40 +58,40 @@ void platformUnprotectST25RComm();
|
||||
|
||||
#define platformIrqST25RSetCallback( cb ) platformSetIrqCallback(cb)
|
||||
|
||||
#define platformProtectST25RIrqStatus() platformProtectST25RComm() /*!< Protect unique access to IRQ status var - IRQ disable on single thread environment (MCU) ; Mutex lock on a multi thread environment */
|
||||
#define platformUnprotectST25RIrqStatus() platformUnprotectST25RComm() /*!< Unprotect the IRQ status var - IRQ enable on a single thread environment (MCU) ; Mutex unlock on a multi thread environment */
|
||||
#define platformProtectST25RIrqStatus() platformProtectST25RComm() /*!< Protect unique access to IRQ status var - IRQ disable on single thread environment (MCU) ; Mutex lock on a multi thread environment */
|
||||
#define platformUnprotectST25RIrqStatus() platformUnprotectST25RComm() /*!< Unprotect the IRQ status var - IRQ enable on a single thread environment (MCU) ; Mutex unlock on a multi thread environment */
|
||||
|
||||
#define platformLedOff( port, pin ) api_hal_light_set(pin, 0x00)
|
||||
#define platformLedOn( port, pin ) api_hal_light_set(pin, 0xFF)
|
||||
#define platformLedOff( port, pin ) api_hal_light_set(pin, 0x00)
|
||||
#define platformLedOn( port, pin ) api_hal_light_set(pin, 0xFF)
|
||||
|
||||
#define platformGpioSet( port, pin ) HAL_GPIO_WritePin(port, pin, GPIO_PIN_SET) /*!< Turns the given GPIO High */
|
||||
#define platformGpioClear( port, pin ) HAL_GPIO_WritePin(port, pin, GPIO_PIN_RESET) /*!< Turns the given GPIO Low */
|
||||
#define platformGpioToogle( port, pin ) HAL_GPIO_TogglePin(port, pin) /*!< Toogles the given GPIO */
|
||||
#define platformGpioIsHigh( port, pin ) (HAL_GPIO_ReadPin(port, pin) == GPIO_PIN_SET) /*!< Checks if the given LED is High */
|
||||
#define platformGpioIsLow( port, pin ) (!platformGpioIsHigh(port, pin)) /*!< Checks if the given LED is Low */
|
||||
#define platformGpioSet( port, pin ) HAL_GPIO_WritePin(port, pin, GPIO_PIN_SET) /*!< Turns the given GPIO High */
|
||||
#define platformGpioClear( port, pin ) HAL_GPIO_WritePin(port, pin, GPIO_PIN_RESET) /*!< Turns the given GPIO Low */
|
||||
#define platformGpioToogle( port, pin ) HAL_GPIO_TogglePin(port, pin) /*!< Toogles the given GPIO */
|
||||
#define platformGpioIsHigh( port, pin ) (HAL_GPIO_ReadPin(port, pin) == GPIO_PIN_SET) /*!< Checks if the given LED is High */
|
||||
#define platformGpioIsLow( port, pin ) (!platformGpioIsHigh(port, pin)) /*!< Checks if the given LED is Low */
|
||||
|
||||
#define platformTimerCreate( t ) timerCalculateTimer(t) /*!< Create a timer with the given time (ms) */
|
||||
#define platformTimerIsExpired( timer ) timerIsExpired(timer) /*!< Checks if the given timer is expired */
|
||||
#define platformDelay( t ) osDelay( t ) /*!< Performs a delay for the given time (ms) */
|
||||
#define platformTimerCreate( t ) timerCalculateTimer(t) /*!< Create a timer with the given time (ms) */
|
||||
#define platformTimerIsExpired( timer ) timerIsExpired(timer) /*!< Checks if the given timer is expired */
|
||||
#define platformDelay( t ) osDelay( t ) /*!< Performs a delay for the given time (ms) */
|
||||
|
||||
#define platformGetSysTick() osKernelGetTickCount() /*!< Get System Tick (1 tick = 1 ms) */
|
||||
#define platformGetSysTick() osKernelGetTickCount() /*!< Get System Tick (1 tick = 1 ms) */
|
||||
|
||||
#define platformAssert( exp ) assert_param( exp ) /*!< Asserts whether the given expression is true*/
|
||||
// #define platformErrorHandle() Error_Handler() /*!< Global error handle\trap */
|
||||
#define platformAssert( exp ) assert_param( exp ) /*!< Asserts whether the given expression is true*/
|
||||
#define platformErrorHandle() Error_Handler() /*!< Global error handle\trap */
|
||||
|
||||
#define platformSpiSelect() platformGpioClear( ST25R_SS_PORT, ST25R_SS_PIN ) /*!< SPI SS\CS: Chip|Slave Select */
|
||||
#define platformSpiDeselect() platformGpioSet( ST25R_SS_PORT, ST25R_SS_PIN ) /*!< SPI SS\CS: Chip|Slave Deselect */
|
||||
#define platformSpiSelect() platformGpioClear( ST25R_SS_PORT, ST25R_SS_PIN ) /*!< SPI SS\CS: Chip|Slave Select */
|
||||
#define platformSpiDeselect() platformGpioSet( ST25R_SS_PORT, ST25R_SS_PIN ) /*!< SPI SS\CS: Chip|Slave Deselect */
|
||||
|
||||
|
||||
#define platformI2CTx( txBuf, len, last, txOnly ) /*!< I2C Transmit */
|
||||
#define platformI2CRx( txBuf, len ) /*!< I2C Receive */
|
||||
#define platformI2CStart() /*!< I2C Start condition */
|
||||
#define platformI2CStop() /*!< I2C Stop condition */
|
||||
#define platformI2CRepeatStart() /*!< I2C Repeat Start */
|
||||
#define platformI2CSlaveAddrWR(add) /*!< I2C Slave address for Write operation */
|
||||
#define platformI2CSlaveAddrRD(add) /*!< I2C Slave address for Read operation */
|
||||
#define platformI2CTx( txBuf, len, last, txOnly ) /*!< I2C Transmit */
|
||||
#define platformI2CRx( txBuf, len ) /*!< I2C Receive */
|
||||
#define platformI2CStart() /*!< I2C Start condition */
|
||||
#define platformI2CStop() /*!< I2C Stop condition */
|
||||
#define platformI2CRepeatStart() /*!< I2C Repeat Start */
|
||||
#define platformI2CSlaveAddrWR(add) /*!< I2C Slave address for Write operation */
|
||||
#define platformI2CSlaveAddrRD(add) /*!< I2C Slave address for Read operation */
|
||||
|
||||
#define platformLog(...) /*!< Log method */
|
||||
#define platformLog(...) /*!< Log method */
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
|
171
lib/drivers/cc1101.c
Normal file
171
lib/drivers/cc1101.c
Normal file
@ -0,0 +1,171 @@
|
||||
#include "cc1101.h"
|
||||
#include <cmsis_os2.h>
|
||||
#include <api-hal-delay.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
CC1101Status cc1101_strobe(const ApiHalSpiDevice* device, uint8_t strobe) {
|
||||
uint8_t tx[1] = { strobe };
|
||||
CC1101Status rx[1] = { 0 };
|
||||
|
||||
hal_gpio_write(device->chip_select, false);
|
||||
while(hal_gpio_read(device->bus->miso));
|
||||
api_hal_spi_bus_trx(device->bus, tx, (uint8_t*)rx, 1, CC1101_TIMEOUT);
|
||||
hal_gpio_write(device->chip_select, true);
|
||||
|
||||
assert(rx[0].CHIP_RDYn == 0);
|
||||
return rx[0];
|
||||
}
|
||||
|
||||
CC1101Status cc1101_write_reg(const ApiHalSpiDevice* device, uint8_t reg, uint8_t data) {
|
||||
uint8_t tx[2] = { reg, data };
|
||||
CC1101Status rx[2] = { 0 };
|
||||
|
||||
hal_gpio_write(device->chip_select, false);
|
||||
while(hal_gpio_read(device->bus->miso));
|
||||
api_hal_spi_bus_trx(device->bus, tx, (uint8_t*)rx, 2, CC1101_TIMEOUT);
|
||||
hal_gpio_write(device->chip_select, true);
|
||||
|
||||
assert((rx[0].CHIP_RDYn|rx[1].CHIP_RDYn) == 0);
|
||||
return rx[1];
|
||||
}
|
||||
|
||||
CC1101Status cc1101_read_reg(const ApiHalSpiDevice* device, uint8_t reg, uint8_t* data) {
|
||||
assert(sizeof(CC1101Status) == 1);
|
||||
uint8_t tx[2] = { reg|CC1101_READ, 0};
|
||||
CC1101Status rx[2] = { 0 };
|
||||
|
||||
hal_gpio_write(device->chip_select, false);
|
||||
while(hal_gpio_read(device->bus->miso));
|
||||
api_hal_spi_bus_trx(device->bus, tx, (uint8_t*)rx, 2, CC1101_TIMEOUT);
|
||||
hal_gpio_write(device->chip_select, true);
|
||||
|
||||
assert((rx[0].CHIP_RDYn) == 0);
|
||||
*data = *(uint8_t*)&rx[1];
|
||||
return rx[0];
|
||||
}
|
||||
|
||||
uint8_t cc1101_get_partnumber(const ApiHalSpiDevice* device) {
|
||||
uint8_t partnumber=0;
|
||||
cc1101_read_reg(device, CC1101_STATUS_PARTNUM|CC1101_BURST, &partnumber);
|
||||
return partnumber;
|
||||
}
|
||||
|
||||
uint8_t cc1101_get_version(const ApiHalSpiDevice* device) {
|
||||
uint8_t version=0;
|
||||
cc1101_read_reg(device, CC1101_STATUS_VERSION|CC1101_BURST, &version);
|
||||
return version;
|
||||
}
|
||||
|
||||
uint8_t cc1101_get_rssi(const ApiHalSpiDevice* device) {
|
||||
uint8_t rssi=0;
|
||||
cc1101_read_reg(device, CC1101_STATUS_RSSI|CC1101_BURST, &rssi);
|
||||
return rssi;
|
||||
}
|
||||
|
||||
void cc1101_reset(const ApiHalSpiDevice* device) {
|
||||
hal_gpio_write(device->chip_select, false);
|
||||
delay_us(1000);
|
||||
hal_gpio_write(device->chip_select, true);
|
||||
delay_us(1000);
|
||||
cc1101_strobe(device, CC1101_STROBE_SRES);
|
||||
}
|
||||
|
||||
void cc1101_shutdown(const ApiHalSpiDevice* device) {
|
||||
cc1101_strobe(device, CC1101_STROBE_SPWD);
|
||||
}
|
||||
|
||||
void cc1101_calibrate(const ApiHalSpiDevice* device) {
|
||||
cc1101_strobe(device, CC1101_STROBE_SCAL);
|
||||
}
|
||||
|
||||
void cc1101_switch_to_idle(const ApiHalSpiDevice* device) {
|
||||
cc1101_strobe(device, CC1101_STROBE_SIDLE);
|
||||
}
|
||||
|
||||
void cc1101_switch_to_rx(const ApiHalSpiDevice* device) {
|
||||
cc1101_strobe(device, CC1101_STROBE_SRX);
|
||||
}
|
||||
|
||||
void cc1101_switch_to_tx(const ApiHalSpiDevice* device) {
|
||||
cc1101_strobe(device, CC1101_STROBE_STX);
|
||||
}
|
||||
|
||||
void cc1101_flush_rx(const ApiHalSpiDevice* device) {
|
||||
cc1101_strobe(device, CC1101_STROBE_SFRX);
|
||||
}
|
||||
|
||||
void cc1101_flush_tx(const ApiHalSpiDevice* device) {
|
||||
cc1101_strobe(device, CC1101_STROBE_SFTX);
|
||||
}
|
||||
|
||||
uint32_t cc1101_set_frequency(const ApiHalSpiDevice* device, uint32_t value) {
|
||||
uint64_t real_value = (uint64_t)value * 0xFFFF / CC1101_QUARTZ;
|
||||
|
||||
// Sanity check
|
||||
assert((real_value & 0xFFFFFF) == real_value);
|
||||
|
||||
cc1101_write_reg(device, CC1101_FREQ2, (real_value >> 16) & 0xFF);
|
||||
cc1101_write_reg(device, CC1101_FREQ1, (real_value >> 8 ) & 0xFF);
|
||||
cc1101_write_reg(device, CC1101_FREQ0, (real_value >> 0 ) & 0xFF);
|
||||
|
||||
uint64_t real_frequency = real_value * CC1101_QUARTZ / 0xFFFF;
|
||||
|
||||
return (uint32_t)real_frequency;
|
||||
}
|
||||
|
||||
uint32_t cc1101_get_frequency_step(const ApiHalSpiDevice* device) {
|
||||
return CC1101_QUARTZ / 0xFFFF;
|
||||
}
|
||||
|
||||
uint32_t cc1101_set_frequency_offset(const ApiHalSpiDevice* device, uint32_t value) {
|
||||
uint64_t real_value = value * 0x4000 / CC1101_QUARTZ;
|
||||
assert((real_value & 0xFF) == real_value);
|
||||
|
||||
cc1101_write_reg(device, CC1101_FSCTRL0, (real_value >> 0 ) & 0xFF);
|
||||
|
||||
uint64_t real_frequency = real_value * CC1101_QUARTZ / 0x4000;
|
||||
|
||||
return (uint32_t)real_frequency;
|
||||
}
|
||||
|
||||
uint32_t cc1101_get_frequency_offset_step(const ApiHalSpiDevice* device) {
|
||||
return CC1101_QUARTZ / 0x4000;
|
||||
}
|
||||
|
||||
void cc1101_set_pa_table(const ApiHalSpiDevice* device, const uint8_t value[8]) {
|
||||
uint8_t tx[9] = { CC1101_PATABLE | CC1101_BURST };
|
||||
CC1101Status rx[9] = { 0 };
|
||||
|
||||
memcpy(&tx[1], &value[0], 8);
|
||||
|
||||
hal_gpio_write(device->chip_select, false);
|
||||
while(hal_gpio_read(device->bus->miso));
|
||||
api_hal_spi_bus_trx(device->bus, tx, (uint8_t*)rx, 2, CC1101_TIMEOUT);
|
||||
hal_gpio_write(device->chip_select, true);
|
||||
|
||||
assert((rx[0].CHIP_RDYn|rx[8].CHIP_RDYn) == 0);
|
||||
}
|
||||
|
||||
uint8_t cc1101_write_fifo(const ApiHalSpiDevice* device, const uint8_t* data, uint8_t size) {
|
||||
uint8_t tx = CC1101_FIFO | CC1101_BURST;
|
||||
CC1101Status rx = { 0 };
|
||||
|
||||
// Start transaction
|
||||
hal_gpio_write(device->chip_select, false);
|
||||
// Wait IC to become ready
|
||||
while(hal_gpio_read(device->bus->miso));
|
||||
// Tell IC what we want
|
||||
api_hal_spi_bus_trx(device->bus, &tx, (uint8_t*)&rx, 1, CC1101_TIMEOUT);
|
||||
assert((rx.CHIP_RDYn) == 0);
|
||||
// Transmit data
|
||||
api_hal_spi_bus_tx(device->bus, (uint8_t*)data, size, CC1101_TIMEOUT);
|
||||
// Finish transaction
|
||||
hal_gpio_write(device->chip_select, true);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
uint8_t cc1101_read_fifo(const ApiHalSpiDevice* device, uint8_t* data, uint8_t size) {
|
||||
return size;
|
||||
}
|
153
lib/drivers/cc1101.h
Normal file
153
lib/drivers/cc1101.h
Normal file
@ -0,0 +1,153 @@
|
||||
#pragma once
|
||||
|
||||
#include "cc1101_regs.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <api-hal-spi.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Low level API */
|
||||
|
||||
/** Strobe command to the device
|
||||
* @param device - pointer to ApiHalSpiDevice
|
||||
* @param strobe - command to execute
|
||||
* @return device status
|
||||
*/
|
||||
CC1101Status cc1101_strobe(const ApiHalSpiDevice* device, uint8_t strobe);
|
||||
|
||||
/** Write device register
|
||||
* @param device - pointer to ApiHalSpiDevice
|
||||
* @param reg - register
|
||||
* @param data - data to write
|
||||
* @return device status
|
||||
*/
|
||||
CC1101Status cc1101_write_reg(const ApiHalSpiDevice* device, uint8_t reg, uint8_t data);
|
||||
|
||||
/** Read device register
|
||||
* @param device - pointer to ApiHalSpiDevice
|
||||
* @param reg - register
|
||||
* @param[out] data - pointer to data
|
||||
* @return device status
|
||||
*/
|
||||
CC1101Status cc1101_read_reg(const ApiHalSpiDevice* device, uint8_t reg, uint8_t* data);
|
||||
|
||||
/* High level API */
|
||||
|
||||
/** Reset
|
||||
* @param device - pointer to ApiHalSpiDevice
|
||||
*/
|
||||
void cc1101_reset(const ApiHalSpiDevice* device);
|
||||
|
||||
/** Enable shutdown mode
|
||||
* @param device - pointer to ApiHalSpiDevice
|
||||
*/
|
||||
void cc1101_shutdown(const ApiHalSpiDevice* device);
|
||||
|
||||
/** Get Partnumber
|
||||
* @param device - pointer to ApiHalSpiDevice
|
||||
*/
|
||||
uint8_t cc1101_get_partnumber(const ApiHalSpiDevice* device);
|
||||
|
||||
/** Get Version
|
||||
* @param device - pointer to ApiHalSpiDevice
|
||||
*/
|
||||
uint8_t cc1101_get_version(const ApiHalSpiDevice* device);
|
||||
|
||||
/** Get raw RSSI value
|
||||
* @param device - pointer to ApiHalSpiDevice
|
||||
*/
|
||||
uint8_t cc1101_get_rssi(const ApiHalSpiDevice* device);
|
||||
|
||||
/** Calibrate oscillator
|
||||
* @param device - pointer to ApiHalSpiDevice
|
||||
*/
|
||||
void cc1101_calibrate(const ApiHalSpiDevice* device);
|
||||
|
||||
/** Switch to idle
|
||||
* @param device - pointer to ApiHalSpiDevice
|
||||
*/
|
||||
void cc1101_switch_to_idle(const ApiHalSpiDevice* device);
|
||||
|
||||
/** Switch to RX
|
||||
* @param device - pointer to ApiHalSpiDevice
|
||||
*/
|
||||
void cc1101_switch_to_rx(const ApiHalSpiDevice* device);
|
||||
|
||||
/** Switch to TX
|
||||
* @param device - pointer to ApiHalSpiDevice
|
||||
*/
|
||||
void cc1101_switch_to_tx(const ApiHalSpiDevice* device);
|
||||
|
||||
/** Flush RX FIFO
|
||||
* @param device - pointer to ApiHalSpiDevice
|
||||
*/
|
||||
void cc1101_flush_rx(const ApiHalSpiDevice* device);
|
||||
|
||||
/** Flush TX FIFO
|
||||
* @param device - pointer to ApiHalSpiDevice
|
||||
*/
|
||||
void cc1101_flush_tx(const ApiHalSpiDevice* device);
|
||||
|
||||
/** Set Frequency
|
||||
* Is not 100% precise, depends on quartz used
|
||||
* @param device - pointer to ApiHalSpiDevice
|
||||
* @param value - frequency in herz
|
||||
* @return real frequency that were set
|
||||
*/
|
||||
uint32_t cc1101_set_frequency(const ApiHalSpiDevice* device, uint32_t value);
|
||||
|
||||
/** Get Frequency Step
|
||||
* @param device - pointer to ApiHalSpiDevice
|
||||
* @return frequency step
|
||||
*/
|
||||
uint32_t cc1101_get_frequency_step(const ApiHalSpiDevice* device);
|
||||
|
||||
/** Set Frequency Offset
|
||||
* Is not 100% precise, depends on quartz used
|
||||
* @param device - pointer to ApiHalSpiDevice
|
||||
* @param value - frequency offset in herz
|
||||
* @return real frequency that were set
|
||||
*/
|
||||
uint32_t cc1101_set_frequency_offset(const ApiHalSpiDevice* device, uint32_t value);
|
||||
|
||||
/** Get Frequency Offset Step
|
||||
* @param device - pointer to ApiHalSpiDevice
|
||||
* @return frequency offset step
|
||||
*/
|
||||
uint32_t cc1101_get_frequency_offset_step(const ApiHalSpiDevice* device);
|
||||
|
||||
/** Set Power Amplifier level table, ramp
|
||||
* @param device - pointer to ApiHalSpiDevice
|
||||
* @param value - array of power level values
|
||||
*/
|
||||
void cc1101_set_pa_table(const ApiHalSpiDevice* device, const uint8_t value[8]);
|
||||
|
||||
/** Set Power Amplifier level table, ramp
|
||||
* @param device - pointer to ApiHalSpiDevice
|
||||
* @param value - array of power level values
|
||||
*/
|
||||
void cc1101_set_pa_table(const ApiHalSpiDevice* device, const uint8_t value[8]);
|
||||
|
||||
/** Write FIFO
|
||||
* @param device - pointer to ApiHalSpiDevice
|
||||
* @param data, pointer to byte array
|
||||
* @param size, write bytes count
|
||||
* @return size, written bytes count
|
||||
*/
|
||||
uint8_t cc1101_write_fifo(const ApiHalSpiDevice* device, const uint8_t* data, uint8_t size);
|
||||
|
||||
/** Read FIFO
|
||||
* @param device - pointer to ApiHalSpiDevice
|
||||
* @param data, pointer to byte array
|
||||
* @param size, bytes to read from fifo
|
||||
* @return size, read bytes count
|
||||
*/
|
||||
uint8_t cc1101_read_fifo(const ApiHalSpiDevice* device, uint8_t* data, uint8_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
131
lib/drivers/cc1101_regs.h
Normal file
131
lib/drivers/cc1101_regs.h
Normal file
@ -0,0 +1,131 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define CC1101_QUARTZ 26000000
|
||||
|
||||
#define CC1101_TIMEOUT 500
|
||||
|
||||
#define CC1101_READ (1<<7) /** Read Bit */
|
||||
#define CC1101_BURST (1<<6) /** Burst Bit */
|
||||
|
||||
/* Common registers, CC1101_BURST and CC1101_WRITE behaves as expected */
|
||||
#define CC1101_IOCFG2 0x00 /** GDO2 output pin configuration */
|
||||
#define CC1101_IOCFG1 0x01 /** GDO1 output pin configuration */
|
||||
#define CC1101_IOCFG0 0x02 /** GDO0 output pin configuration */
|
||||
#define CC1101_FIFOTHR 0x03 /** RX FIFO and TX FIFO thresholds */
|
||||
#define CC1101_SYNC1 0x04 /** Sync word, high byte */
|
||||
#define CC1101_SYNC0 0x05 /** Sync word, low byte */
|
||||
#define CC1101_PKTLEN 0x06 /** Packet length */
|
||||
#define CC1101_PKTCTRL1 0x07 /** Packet automation control */
|
||||
#define CC1101_PKTCTRL0 0x08 /** Packet automation control */
|
||||
#define CC1101_ADDR 0x09 /** Device address */
|
||||
#define CC1101_CHANNR 0x0A /** Channel number */
|
||||
#define CC1101_FSCTRL1 0x0B /** Frequency synthesizer control */
|
||||
#define CC1101_FSCTRL0 0x0C /** Frequency synthesizer control */
|
||||
#define CC1101_FREQ2 0x0D /** Frequency control word, high byte */
|
||||
#define CC1101_FREQ1 0x0E /** Frequency control word, middle byte */
|
||||
#define CC1101_FREQ0 0x0F /** Frequency control word, low byte */
|
||||
#define CC1101_MDMCFG4 0x10 /** Modem configuration */
|
||||
#define CC1101_MDMCFG3 0x11 /** Modem configuration */
|
||||
#define CC1101_MDMCFG2 0x12 /** Modem configuration */
|
||||
#define CC1101_MDMCFG1 0x13 /** Modem configuration */
|
||||
#define CC1101_MDMCFG0 0x14 /** Modem configuration */
|
||||
#define CC1101_DEVIATN 0x15 /** Modem deviation setting */
|
||||
#define CC1101_MCSM2 0x16 /** Main Radio Control State Machine configuration */
|
||||
#define CC1101_MCSM1 0x17 /** Main Radio Control State Machine configuration */
|
||||
#define CC1101_MCSM0 0x18 /** Main Radio Control State Machine configuration */
|
||||
#define CC1101_FOCCFG 0x19 /** Frequency Offset Compensation configuration */
|
||||
#define CC1101_BSCFG 0x1A /** Bit Synchronization configuration */
|
||||
#define CC1101_AGCTRL2 0x1B /** AGC control */
|
||||
#define CC1101_AGCTRL1 0x1C /** AGC control */
|
||||
#define CC1101_AGCTRL0 0x1D /** AGC control */
|
||||
#define CC1101_WOREVT1 0x1E /** High byte Event 0 timeout */
|
||||
#define CC1101_WOREVT0 0x1F /** Low byte Event 0 timeout */
|
||||
#define CC1101_WORCTRL 0x20 /** Wake On Radio control */
|
||||
#define CC1101_FREND1 0x21 /** Front end RX configuration */
|
||||
#define CC1101_FREND0 0x22 /** Front end TX configuration */
|
||||
#define CC1101_FSCAL3 0x23 /** Frequency synthesizer calibration */
|
||||
#define CC1101_FSCAL2 0x24 /** Frequency synthesizer calibration */
|
||||
#define CC1101_FSCAL1 0x25 /** Frequency synthesizer calibration */
|
||||
#define CC1101_FSCAL0 0x26 /** Frequency synthesizer calibration */
|
||||
#define CC1101_RCCTRL1 0x27 /** RC oscillator configuration */
|
||||
#define CC1101_RCCTRL0 0x28 /** RC oscillator configuration */
|
||||
#define CC1101_FSTEST 0x29 /** Frequency synthesizer calibration control */
|
||||
#define CC1101_PTEST 0x2A /** Production test */
|
||||
#define CC1101_AGCTEST 0x2B /** AGC test */
|
||||
#define CC1101_TEST2 0x2C /** Various test settings */
|
||||
#define CC1101_TEST1 0x2D /** Various test settings */
|
||||
#define CC1101_TEST0 0x2E /** Various test settings */
|
||||
|
||||
/* Strobe registers, CC1101_BURST is not available, CC1101_WRITE ignored */
|
||||
#define CC1101_STROBE_SRES 0x30 /** Reset chip. */
|
||||
#define CC1101_STROBE_SFSTXON 0x31 /** Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1). If in RX (with CCA): Go to a wait state where only the synthesizer is running (for quick RX / TX turnaround). */
|
||||
#define CC1101_STROBE_SXOFF 0x32 /** Turn off crystal oscillator. */
|
||||
#define CC1101_STROBE_SCAL 0x33 /** Calibrate frequency synthesizer and turn it off. SCAL can be strobed from IDLE mode without setting manual calibration mode (MCSM0.FS_AUTOCAL=0) */
|
||||
#define CC1101_STROBE_SRX 0x34 /** Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1. */
|
||||
#define CC1101_STROBE_STX 0x35 /** In IDLE state: Enable TX. Perform calibration first if MCSM0.FS_AUTOCAL=1. If in RX state and CCA is enabled: Only go to TX if channel is clear. */
|
||||
#define CC1101_STROBE_SIDLE 0x36 /** Exit RX / TX, turn off frequency synthesizer and exit Wake-On-Radio mode if applicable. */
|
||||
#define CC1101_STROBE_SWOR 0x38 /** Start automatic RX polling sequence (Wake-on-Radio) as described in Section 19.5 if WORCTRL.RC_PD=0. */
|
||||
/* 0x37 is unused */
|
||||
#define CC1101_STROBE_SPWD 0x39 /** Enter power down mode when CSn goes high. */
|
||||
#define CC1101_STROBE_SFRX 0x3A /** Flush the RX FIFO buffer. Only issue SFRX in IDLE or RXFIFO_OVERFLOW states. */
|
||||
#define CC1101_STROBE_SFTX 0x3B /** Flush the TX FIFO buffer. Only issue SFTX in IDLE or TXFIFO_UNDERFLOW states. */
|
||||
#define CC1101_STROBE_SWORRST 0x3C /** Reset real time clock to Event1 value. */
|
||||
#define CC1101_STROBE_SNOP 0x3D /** No operation. May be used to get access to the chip status byte.*/
|
||||
|
||||
/* Status registers, must be accessed with CC1101_BURST, but one by one */
|
||||
#define CC1101_STATUS_PARTNUM 0x30 /** Chip ID Part Number */
|
||||
#define CC1101_STATUS_VERSION 0x31 /** Chip ID Version */
|
||||
#define CC1101_STATUS_FREQEST 0x32 /** Frequency Offset Estimate from Demodulator */
|
||||
#define CC1101_STATUS_LQI 0x33 /** Demodulator Estimate for Link Quality */
|
||||
#define CC1101_STATUS_RSSI 0x34 /** Received Signal Strength Indication */
|
||||
#define CC1101_STATUS_MARCSTATE 0x35 /** Main Radio Control State Machine State */
|
||||
#define CC1101_STATUS_WORTIME1 0x36 /** High Byte of WOR Time */
|
||||
#define CC1101_STATUS_WORTIME0 0x37 /** Low Byte of WOR Time */
|
||||
#define CC1101_STATUS_PKTSTATUS 0x38 /** Current GDOx Status and Packet Status */
|
||||
#define CC1101_STATUS_VCO_VC_DAC 0x39 /** Current Setting from PLL Calibration Module */
|
||||
#define CC1101_STATUS_TXBYTES 0x3A /** Underflow and Number of Bytes */
|
||||
#define CC1101_STATUS_RXBYTES 0x3B /** Overflow and Number of Bytes */
|
||||
#define CC1101_STATUS_RCCTRL1_STATUS 0x3C /** Last RC Oscillator Calibration Result */
|
||||
#define CC1101_STATUS_RCCTRL0_STATUS 0x3D /** Last RC Oscillator Calibration Result */
|
||||
|
||||
/* Some special registers, use CC1101_BURST to read/write data */
|
||||
#define CC1101_PATABLE 0x3E /** PATABLE register number, an 8-byte table that defines the PA control settings */
|
||||
#define CC1101_FIFO 0x3F /** FIFO register nunmber, can be combined with CC1101_WRITE and/or CC1101_BURST */
|
||||
|
||||
typedef enum {
|
||||
CC1101StateIDLE=0b000, /** IDLE state */
|
||||
CC1101StateRX=0b001, /** Receive mode */
|
||||
CC1101StateTX=0b010, /** Transmit mode */
|
||||
CC1101StateFSTXON=0b011, /** Fast TX ready */
|
||||
CC1101StateCALIBRATE=0b100, /** Frequency synthesizer calibration is running */
|
||||
CC1101StateSETTLING=0b101, /** PLL is settling */
|
||||
CC1101StateRXFIFO_OVERFLOW=0b110, /** RX FIFO has overflowed. Read out any useful data, then flush the FIFO with SFRX */
|
||||
CC1101StateTXFIFO_UNDERFLOW=0b111, /** TX FIFO has underflowed. Acknowledge with SFTX */
|
||||
} CC1101State;
|
||||
|
||||
typedef struct {
|
||||
uint8_t FIFO_BYTES_AVAILABLE:4;
|
||||
CC1101State STATE:3;
|
||||
bool CHIP_RDYn:1;
|
||||
} CC1101Status;
|
||||
|
||||
typedef struct {
|
||||
uint8_t NUM_TXBYTES:7;
|
||||
bool TXFIFO_UNDERFLOW:1;
|
||||
} CC1101TxBytes;
|
||||
|
||||
typedef struct {
|
||||
uint8_t NUM_RXBYTES:7;
|
||||
bool RXFIFO_OVERFLOW:1;
|
||||
} CC1101RxBytes;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user