commit 0a40daf4fad5c1593c6e1696ac0cab992c799e2e Author: krolyxon Date: Mon May 4 22:48:07 2026 +0530 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..401d1aa --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +schmatics +documentation + +# Clangd cache +.cache diff --git a/assets/initial_workflow_diagram.png b/assets/initial_workflow_diagram.png new file mode 100644 index 0000000..782b9b4 Binary files /dev/null and b/assets/initial_workflow_diagram.png differ diff --git a/firmware/ELECHOUSE_CC1101_SRC_DRV.cpp b/firmware/ELECHOUSE_CC1101_SRC_DRV.cpp new file mode 100644 index 0000000..5568989 --- /dev/null +++ b/firmware/ELECHOUSE_CC1101_SRC_DRV.cpp @@ -0,0 +1,1309 @@ +/* + ELECHOUSE_CC1101.cpp - CC1101 module library + Copyright (c) 2010 Michael. + Author: Michael, + Version: November 12, 2010 + + This library is designed to use CC1101/CC1100 module on Arduino platform. + CC1101/CC1100 module is an useful wireless module.Using the functions of the + library, you can easily send and receive data by the CC1101/CC1100 module. + Just have fun! + For the details, please refer to the datasheet of CC1100/CC1101. +---------------------------------------------------------------------------------------------------------------- +cc1101 Driver for RC Switch. Mod by Little Satan. With permission to modify and publish Wilson Shen (ELECHOUSE). +---------------------------------------------------------------------------------------------------------------- +*/ +#include +#include "ELECHOUSE_CC1101_SRC_DRV.h" +#include + +/****************************************************************/ +#define WRITE_BURST 0x40 //write burst +#define READ_SINGLE 0x80 //read single +#define READ_BURST 0xC0 //read burst +#define BYTES_IN_RXFIFO 0x7F //byte number in RXfifo +#define max_modul 6 + +SPIClass CCSPI(HSPI); + +byte modulation = 2; +byte frend0; +byte chan = 0; +int pa = 12; +byte last_pa; +byte SCK_PIN; +byte MISO_PIN; +byte MOSI_PIN; +byte SS_PIN; +byte GDO0; +byte GDO2; +byte SCK_PIN_M[max_modul]; +byte MISO_PIN_M[max_modul]; +byte MOSI_PIN_M[max_modul]; +byte SS_PIN_M[max_modul]; +byte GDO0_M[max_modul]; +byte GDO2_M[max_modul]; +byte gdo_set=0; +bool spi = 0; +bool ccmode = 0; +float MHz = 433.92; +byte m4RxBw = 0; +byte m4DaRa; +byte m2DCOFF; +byte m2MODFM; +byte m2MANCH; +byte m2SYNCM; +byte m1FEC; +byte m1PRE; +byte m1CHSP; +byte pc1PQT; +byte pc1CRC_AF; +byte pc1APP_ST; +byte pc1ADRCHK; +byte pc0WDATA; +byte pc0PktForm; +byte pc0CRC_EN; +byte pc0LenConf; +byte trxstate = 0; +byte clb1[2]= {24,28}; +byte clb2[2]= {31,38}; +byte clb3[2]= {65,76}; +byte clb4[2]= {77,79}; + +/****************************************************************/ +uint8_t PA_TABLE[8] {0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00}; +// -30 -20 -15 -10 0 5 7 10 +uint8_t PA_TABLE_315[8] {0x12,0x0D,0x1C,0x34,0x51,0x85,0xCB,0xC2,}; //300 - 348 +uint8_t PA_TABLE_433[8] {0x12,0x0E,0x1D,0x34,0x60,0x84,0xC8,0xC0,}; //387 - 464 +// -30 -20 -15 -10 -6 0 5 7 10 12 +uint8_t PA_TABLE_868[10] {0x03,0x17,0x1D,0x26,0x37,0x50,0x86,0xCD,0xC5,0xC0,}; //779 - 899.99 +// -30 -20 -15 -10 -6 0 5 7 10 11 +uint8_t PA_TABLE_915[10] {0x03,0x0E,0x1E,0x27,0x38,0x8E,0x84,0xCC,0xC3,0xC0,}; //900 - 928 +/**************************************************************** +*FUNCTION NAME:SpiStart +*FUNCTION :spi communication start +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::SpiStart(void) +{ + // initialize the SPI pins + pinMode(SCK_PIN, OUTPUT); + pinMode(MOSI_PIN, OUTPUT); + pinMode(MISO_PIN, INPUT); + pinMode(SS_PIN, OUTPUT); + + // enable SPI + #ifdef ESP32 + CCSPI.begin(SCK_PIN, MISO_PIN, MOSI_PIN, SS_PIN); + #else + CCSPI.begin(); + #endif +} +/**************************************************************** +*FUNCTION NAME:SpiEnd +*FUNCTION :spi communication disable +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::SpiEnd(void) +{ + // disable SPI + CCSPI.endTransaction(); + CCSPI.end(); +} +/**************************************************************** +*FUNCTION NAME: GDO_Set() +*FUNCTION : set GDO0,GDO2 pin for serial pinmode. +*INPUT : none +*OUTPUT : none +****************************************************************/ +void ELECHOUSE_CC1101::GDO_Set (void) +{ + pinMode(GDO0, OUTPUT); + pinMode(GDO2, INPUT); +} +/**************************************************************** +*FUNCTION NAME: GDO_Set() +*FUNCTION : set GDO0 for internal transmission mode. +*INPUT : none +*OUTPUT : none +****************************************************************/ +void ELECHOUSE_CC1101::GDO0_Set (void) +{ + pinMode(GDO0, INPUT); +} +/**************************************************************** +*FUNCTION NAME:Reset +*FUNCTION :CC1101 reset //details refer datasheet of CC1101/CC1100// +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::Reset (void) +{ + digitalWrite(SS_PIN, LOW); + delay(1); + digitalWrite(SS_PIN, HIGH); + delay(1); + digitalWrite(SS_PIN, LOW); + while(digitalRead(MISO_PIN)); + CCSPI.transfer(CC1101_SRES); + while(digitalRead(MISO_PIN)); + digitalWrite(SS_PIN, HIGH); +} +/**************************************************************** +*FUNCTION NAME:Init +*FUNCTION :CC1101 initialization +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::Init(void) +{ + setSpi(); + SpiStart(); //spi initialization + digitalWrite(SS_PIN, HIGH); + digitalWrite(SCK_PIN, HIGH); + digitalWrite(MOSI_PIN, LOW); + Reset(); //CC1101 reset + RegConfigSettings(); //CC1101 register config + SpiEnd(); +} +/**************************************************************** +*FUNCTION NAME:SpiWriteReg +*FUNCTION :CC1101 write data to register +*INPUT :addr: register address; value: register value +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::SpiWriteReg(byte addr, byte value) +{ + SpiStart(); + digitalWrite(SS_PIN, LOW); + while(digitalRead(MISO_PIN)); + CCSPI.transfer(addr); + CCSPI.transfer(value); + digitalWrite(SS_PIN, HIGH); + SpiEnd(); +} +/**************************************************************** +*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 ELECHOUSE_CC1101::SpiWriteBurstReg(byte addr, byte *buffer, byte num) +{ + byte i, temp; + SpiStart(); + temp = addr | WRITE_BURST; + digitalWrite(SS_PIN, LOW); + while(digitalRead(MISO_PIN)); + CCSPI.transfer(temp); + for (i = 0; i < num; i++) + { + CCSPI.transfer(buffer[i]); + } + digitalWrite(SS_PIN, HIGH); + SpiEnd(); +} +/**************************************************************** +*FUNCTION NAME:SpiStrobe +*FUNCTION :CC1101 Strobe +*INPUT :strobe: command; //refer define in CC1101.h// +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::SpiStrobe(byte strobe) +{ + SpiStart(); + digitalWrite(SS_PIN, LOW); + while(digitalRead(MISO_PIN)); + CCSPI.transfer(strobe); + digitalWrite(SS_PIN, HIGH); + SpiEnd(); +} +/**************************************************************** +*FUNCTION NAME:SpiReadReg +*FUNCTION :CC1101 read data from register +*INPUT :addr: register address +*OUTPUT :register value +****************************************************************/ +byte ELECHOUSE_CC1101::SpiReadReg(byte addr) +{ + byte temp, value; + SpiStart(); + temp = addr| READ_SINGLE; + digitalWrite(SS_PIN, LOW); + while(digitalRead(MISO_PIN)); + CCSPI.transfer(temp); + value=CCSPI.transfer(0); + digitalWrite(SS_PIN, HIGH); + SpiEnd(); + 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 ELECHOUSE_CC1101::SpiReadBurstReg(byte addr, byte *buffer, byte num) +{ + byte i,temp; + SpiStart(); + temp = addr | READ_BURST; + digitalWrite(SS_PIN, LOW); + while(digitalRead(MISO_PIN)); + CCSPI.transfer(temp); + for(i=0;i4){m=4;} +modulation = m; +Split_MDMCFG2(); +switch (m) +{ +case 0: m2MODFM=0x00; frend0=0x10; break; // 2-FSK +case 1: m2MODFM=0x10; frend0=0x10; break; // GFSK +case 2: m2MODFM=0x30; frend0=0x11; break; // ASK +case 3: m2MODFM=0x40; frend0=0x10; break; // 4-FSK +case 4: m2MODFM=0x70; frend0=0x10; break; // MSK +} +SpiWriteReg(CC1101_MDMCFG2, m2DCOFF+m2MODFM+m2MANCH+m2SYNCM); +SpiWriteReg(CC1101_FREND0, frend0); +setPA(pa); +} +/**************************************************************** +*FUNCTION NAME:PA Power +*FUNCTION :set CC1101 PA Power +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setPA(int p) +{ +int a; +pa = p; + +if (MHz >= 300 && MHz <= 348){ +if (pa <= -30){a = PA_TABLE_315[0];} +else if (pa > -30 && pa <= -20){a = PA_TABLE_315[1];} +else if (pa > -20 && pa <= -15){a = PA_TABLE_315[2];} +else if (pa > -15 && pa <= -10){a = PA_TABLE_315[3];} +else if (pa > -10 && pa <= 0){a = PA_TABLE_315[4];} +else if (pa > 0 && pa <= 5){a = PA_TABLE_315[5];} +else if (pa > 5 && pa <= 7){a = PA_TABLE_315[6];} +else if (pa > 7){a = PA_TABLE_315[7];} +last_pa = 1; +} +else if (MHz >= 378 && MHz <= 464){ +if (pa <= -30){a = PA_TABLE_433[0];} +else if (pa > -30 && pa <= -20){a = PA_TABLE_433[1];} +else if (pa > -20 && pa <= -15){a = PA_TABLE_433[2];} +else if (pa > -15 && pa <= -10){a = PA_TABLE_433[3];} +else if (pa > -10 && pa <= 0){a = PA_TABLE_433[4];} +else if (pa > 0 && pa <= 5){a = PA_TABLE_433[5];} +else if (pa > 5 && pa <= 7){a = PA_TABLE_433[6];} +else if (pa > 7){a = PA_TABLE_433[7];} +last_pa = 2; +} +else if (MHz >= 779 && MHz <= 899.99){ +if (pa <= -30){a = PA_TABLE_868[0];} +else if (pa > -30 && pa <= -20){a = PA_TABLE_868[1];} +else if (pa > -20 && pa <= -15){a = PA_TABLE_868[2];} +else if (pa > -15 && pa <= -10){a = PA_TABLE_868[3];} +else if (pa > -10 && pa <= -6){a = PA_TABLE_868[4];} +else if (pa > -6 && pa <= 0){a = PA_TABLE_868[5];} +else if (pa > 0 && pa <= 5){a = PA_TABLE_868[6];} +else if (pa > 5 && pa <= 7){a = PA_TABLE_868[7];} +else if (pa > 7 && pa <= 10){a = PA_TABLE_868[8];} +else if (pa > 10){a = PA_TABLE_868[9];} +last_pa = 3; +} +else if (MHz >= 900 && MHz <= 928){ +if (pa <= -30){a = PA_TABLE_915[0];} +else if (pa > -30 && pa <= -20){a = PA_TABLE_915[1];} +else if (pa > -20 && pa <= -15){a = PA_TABLE_915[2];} +else if (pa > -15 && pa <= -10){a = PA_TABLE_915[3];} +else if (pa > -10 && pa <= -6){a = PA_TABLE_915[4];} +else if (pa > -6 && pa <= 0){a = PA_TABLE_915[5];} +else if (pa > 0 && pa <= 5){a = PA_TABLE_915[6];} +else if (pa > 5 && pa <= 7){a = PA_TABLE_915[7];} +else if (pa > 7 && pa <= 10){a = PA_TABLE_915[8];} +else if (pa > 10){a = PA_TABLE_915[9];} +last_pa = 4; +} +if (modulation == 2){ +PA_TABLE[0] = 0; +PA_TABLE[1] = a; +}else{ +PA_TABLE[0] = a; +PA_TABLE[1] = 0; +} +SpiWriteBurstReg(CC1101_PATABLE,PA_TABLE,8); +} +/**************************************************************** +*FUNCTION NAME:Frequency Calculator +*FUNCTION :Calculate the basic frequency. +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setMHZ(float mhz){ +byte freq2 = 0; +byte freq1 = 0; +byte freq0 = 0; + +MHz = mhz; + +for (bool i = 0; i==0;){ +if (mhz >= 26){ +mhz-=26; +freq2+=1; +} +else if (mhz >= 0.1015625){ +mhz-=0.1015625; +freq1+=1; +} +else if (mhz >= 0.00039675){ +mhz-=0.00039675; +freq0+=1; +} +else{i=1;} +} +if (freq0 > 255){freq1+=1;freq0-=256;} + +SpiWriteReg(CC1101_FREQ2, freq2); +SpiWriteReg(CC1101_FREQ1, freq1); +SpiWriteReg(CC1101_FREQ0, freq0); + +Calibrate(); +} +/**************************************************************** +*FUNCTION NAME:Calibrate +*FUNCTION :Calibrate frequency +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::Calibrate(void){ + +if (MHz >= 300 && MHz <= 348){ +SpiWriteReg(CC1101_FSCTRL0, map(MHz, 300, 348, clb1[0], clb1[1])); +if (MHz < 322.88){SpiWriteReg(CC1101_TEST0,0x0B);} +else{ +SpiWriteReg(CC1101_TEST0,0x09); +int s = ELECHOUSE_cc1101.SpiReadStatus(CC1101_FSCAL2); +if (s<32){SpiWriteReg(CC1101_FSCAL2, s+32);} +if (last_pa != 1){setPA(pa);} +} +} +else if (MHz >= 378 && MHz <= 464){ +SpiWriteReg(CC1101_FSCTRL0, map(MHz, 378, 464, clb2[0], clb2[1])); +if (MHz < 430.5){SpiWriteReg(CC1101_TEST0,0x0B);} +else{ +SpiWriteReg(CC1101_TEST0,0x09); +int s = ELECHOUSE_cc1101.SpiReadStatus(CC1101_FSCAL2); +if (s<32){SpiWriteReg(CC1101_FSCAL2, s+32);} +if (last_pa != 2){setPA(pa);} +} +} +else if (MHz >= 779 && MHz <= 899.99){ +SpiWriteReg(CC1101_FSCTRL0, map(MHz, 779, 899, clb3[0], clb3[1])); +if (MHz < 861){SpiWriteReg(CC1101_TEST0,0x0B);} +else{ +SpiWriteReg(CC1101_TEST0,0x09); +int s = ELECHOUSE_cc1101.SpiReadStatus(CC1101_FSCAL2); +if (s<32){SpiWriteReg(CC1101_FSCAL2, s+32);} +if (last_pa != 3){setPA(pa);} +} +} +else if (MHz >= 900 && MHz <= 928){ +SpiWriteReg(CC1101_FSCTRL0, map(MHz, 900, 928, clb4[0], clb4[1])); +SpiWriteReg(CC1101_TEST0,0x09); +int s = ELECHOUSE_cc1101.SpiReadStatus(CC1101_FSCAL2); +if (s<32){SpiWriteReg(CC1101_FSCAL2, s+32);} +if (last_pa != 4){setPA(pa);} +} +} +/**************************************************************** +*FUNCTION NAME:Calibration offset +*FUNCTION :Set calibration offset +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setClb(byte b, byte s, byte e){ +if (b == 1){ +clb1[0]=s; +clb1[1]=e; +} +else if (b == 2){ +clb2[0]=s; +clb2[1]=e; +} +else if (b == 3){ +clb3[0]=s; +clb3[1]=e; +} +else if (b == 4){ +clb4[0]=s; +clb4[1]=e; +} +} +/**************************************************************** +*FUNCTION NAME:getCC1101 +*FUNCTION :Test Spi connection and return 1 when true. +*INPUT :none +*OUTPUT :none +****************************************************************/ +bool ELECHOUSE_CC1101::getCC1101(void){ +setSpi(); +if (SpiReadStatus(0x31)>0){ +return 1; +}else{ +return 0; +} +} +/**************************************************************** +*FUNCTION NAME:getMode +*FUNCTION :Return the Mode. Sidle = 0, TX = 1, Rx = 2. +*INPUT :none +*OUTPUT :none +****************************************************************/ +byte ELECHOUSE_CC1101::getMode(void){ +return trxstate; +} +/**************************************************************** +*FUNCTION NAME:Set Sync_Word +*FUNCTION :Sync Word +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setSyncWord(byte sh, byte sl){ +SpiWriteReg(CC1101_SYNC1, sh); +SpiWriteReg(CC1101_SYNC0, sl); +} +/**************************************************************** +*FUNCTION NAME:Set ADDR +*FUNCTION :Address used for packet filtration. Optional broadcast addresses are 0 (0x00) and 255 (0xFF). +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setAddr(byte v){ +SpiWriteReg(CC1101_ADDR, v); +} +/**************************************************************** +*FUNCTION NAME:Set PQT +*FUNCTION :Preamble quality estimator threshold +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setPQT(byte v){ +Split_PKTCTRL1(); +pc1PQT = 0; +if (v>7){v=7;} +pc1PQT = v*32; +SpiWriteReg(CC1101_PKTCTRL1, pc1PQT+pc1CRC_AF+pc1APP_ST+pc1ADRCHK); +} +/**************************************************************** +*FUNCTION NAME:Set CRC_AUTOFLUSH +*FUNCTION :Enable automatic flush of RX FIFO when CRC is not OK +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setCRC_AF(bool v){ +Split_PKTCTRL1(); +pc1CRC_AF = 0; +if (v==1){pc1CRC_AF=8;} +SpiWriteReg(CC1101_PKTCTRL1, pc1PQT+pc1CRC_AF+pc1APP_ST+pc1ADRCHK); +} +/**************************************************************** +*FUNCTION NAME:Set APPEND_STATUS +*FUNCTION :When enabled, two status bytes will be appended to the payload of the packet +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setAppendStatus(bool v){ +Split_PKTCTRL1(); +pc1APP_ST = 0; +if (v==1){pc1APP_ST=4;} +SpiWriteReg(CC1101_PKTCTRL1, pc1PQT+pc1CRC_AF+pc1APP_ST+pc1ADRCHK); +} +/**************************************************************** +*FUNCTION NAME:Set ADR_CHK +*FUNCTION :Controls address check configuration of received packages +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setAdrChk(byte v){ +Split_PKTCTRL1(); +pc1ADRCHK = 0; +if (v>3){v=3;} +pc1ADRCHK = v; +SpiWriteReg(CC1101_PKTCTRL1, pc1PQT+pc1CRC_AF+pc1APP_ST+pc1ADRCHK); +} +/**************************************************************** +*FUNCTION NAME:Set WHITE_DATA +*FUNCTION :Turn data whitening on / off. +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setWhiteData(bool v){ +Split_PKTCTRL0(); +pc0WDATA = 0; +if (v == 1){pc0WDATA=64;} +SpiWriteReg(CC1101_PKTCTRL0, pc0WDATA+pc0PktForm+pc0CRC_EN+pc0LenConf); +} +/**************************************************************** +*FUNCTION NAME:Set PKT_FORMAT +*FUNCTION :Format of RX and TX data +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setPktFormat(byte v){ +Split_PKTCTRL0(); +pc0PktForm = 0; +if (v>3){v=3;} +pc0PktForm = v*16; +SpiWriteReg(CC1101_PKTCTRL0, pc0WDATA+pc0PktForm+pc0CRC_EN+pc0LenConf); +} +/**************************************************************** +*FUNCTION NAME:Set CRC +*FUNCTION :CRC calculation in TX and CRC check in RX +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setCrc(bool v){ +Split_PKTCTRL0(); +pc0CRC_EN = 0; +if (v==1){pc0CRC_EN=4;} +SpiWriteReg(CC1101_PKTCTRL0, pc0WDATA+pc0PktForm+pc0CRC_EN+pc0LenConf); +} +/**************************************************************** +*FUNCTION NAME:Set LENGTH_CONFIG +*FUNCTION :Configure the packet length +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setLengthConfig(byte v){ +Split_PKTCTRL0(); +pc0LenConf = 0; +if (v>3){v=3;} +pc0LenConf = v; +SpiWriteReg(CC1101_PKTCTRL0, pc0WDATA+pc0PktForm+pc0CRC_EN+pc0LenConf); +} +/**************************************************************** +*FUNCTION NAME:Set PACKET_LENGTH +*FUNCTION :Indicates the packet length +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setPacketLength(byte v){ +SpiWriteReg(CC1101_PKTLEN, v); +} +/**************************************************************** +*FUNCTION NAME:Set DCFILT_OFF +*FUNCTION :Disable digital DC blocking filter before demodulator +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setDcFilterOff(bool v){ +Split_MDMCFG2(); +m2DCOFF = 0; +if (v==1){m2DCOFF=128;} +SpiWriteReg(CC1101_MDMCFG2, m2DCOFF+m2MODFM+m2MANCH+m2SYNCM); +} +/**************************************************************** +*FUNCTION NAME:Set MANCHESTER +*FUNCTION :Enables Manchester encoding/decoding +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setManchester(bool v){ +Split_MDMCFG2(); +m2MANCH = 0; +if (v==1){m2MANCH=8;} +SpiWriteReg(CC1101_MDMCFG2, m2DCOFF+m2MODFM+m2MANCH+m2SYNCM); +} +/**************************************************************** +*FUNCTION NAME:Set SYNC_MODE +*FUNCTION :Combined sync-word qualifier mode +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setSyncMode(byte v){ +Split_MDMCFG2(); +m2SYNCM = 0; +if (v>7){v=7;} +m2SYNCM=v; +SpiWriteReg(CC1101_MDMCFG2, m2DCOFF+m2MODFM+m2MANCH+m2SYNCM); +} +/**************************************************************** +*FUNCTION NAME:Set FEC +*FUNCTION :Enable Forward Error Correction (FEC) +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setFEC(bool v){ +Split_MDMCFG1(); +m1FEC=0; +if (v==1){m1FEC=128;} +SpiWriteReg(CC1101_MDMCFG1, m1FEC+m1PRE+m1CHSP); +} +/**************************************************************** +*FUNCTION NAME:Set PRE +*FUNCTION :Sets the minimum number of preamble bytes to be transmitted. +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setPRE(byte v){ +Split_MDMCFG1(); +m1PRE=0; +if (v>7){v=7;} +m1PRE = v*16; +SpiWriteReg(CC1101_MDMCFG1, m1FEC+m1PRE+m1CHSP); +} +/**************************************************************** +*FUNCTION NAME:Set Channel +*FUNCTION :none +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setChannel(byte ch){ +chan = ch; +SpiWriteReg(CC1101_CHANNR, chan); +} +/**************************************************************** +*FUNCTION NAME:Set Channel spacing +*FUNCTION :none +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setChsp(float f){ +Split_MDMCFG1(); +byte MDMCFG0 = 0; +m1CHSP = 0; +if (f > 405.456543){f = 405.456543;} +if (f < 25.390625){f = 25.390625;} +for (int i = 0; i<5; i++){ +if (f <= 50.682068){ +f -= 25.390625; +f /= 0.0991825; +MDMCFG0 = f; +float s1 = (f - MDMCFG0) *10; +if (s1 >= 5){MDMCFG0++;} +i = 5; +}else{ +m1CHSP++; +f/=2; +} +} +SpiWriteReg(19,m1CHSP+m1FEC+m1PRE); +SpiWriteReg(20,MDMCFG0); +} +/**************************************************************** +*FUNCTION NAME:Set Receive bandwidth +*FUNCTION :none +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setRxBW(float f){ +Split_MDMCFG4(); +int s1 = 3; +int s2 = 3; +for (int i = 0; i<3; i++){ +if (f > 101.5625){f/=2; s1--;} +else{i=3;} +} +for (int i = 0; i<3; i++){ +if (f > 58.1){f/=1.25; s2--;} +else{i=3;} +} +s1 *= 64; +s2 *= 16; +m4RxBw = s1 + s2; +SpiWriteReg(16,m4RxBw+m4DaRa); +} +/**************************************************************** +*FUNCTION NAME:Set Data Rate +*FUNCTION :none +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setDRate(float d){ +Split_MDMCFG4(); +float c = d; +byte MDMCFG3 = 0; +if (c > 1621.83){c = 1621.83;} +if (c < 0.0247955){c = 0.0247955;} +m4DaRa = 0; +for (int i = 0; i<20; i++){ +if (c <= 0.0494942){ +c = c - 0.0247955; +c = c / 0.00009685; +MDMCFG3 = c; +float s1 = (c - MDMCFG3) *10; +if (s1 >= 5){MDMCFG3++;} +i = 20; +}else{ +m4DaRa++; +c = c/2; +} +} +SpiWriteReg(16, m4RxBw+m4DaRa); +SpiWriteReg(17, MDMCFG3); +} +/**************************************************************** +*FUNCTION NAME:Set Devitation +*FUNCTION :none +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setDeviation(float d){ +float f = 1.586914; +float v = 0.19836425; +int c = 0; +if (d > 380.859375){d = 380.859375;} +if (d < 1.586914){d = 1.586914;} +for (int i = 0; i<255; i++){ +f+=v; +if (c==7){v*=2;c=-1;i+=8;} +if (f>=d){c=i;i=255;} +c++; +} +SpiWriteReg(21,c); +} +/**************************************************************** +*FUNCTION NAME:Split PKTCTRL0 +*FUNCTION :none +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::Split_PKTCTRL1(void){ +int calc = SpiReadStatus(7); +pc1PQT = 0; +pc1CRC_AF = 0; +pc1APP_ST = 0; +pc1ADRCHK = 0; +for (bool i = 0; i==0;){ +if (calc >= 32){calc-=32; pc1PQT+=32;} +else if (calc >= 8){calc-=8; pc1CRC_AF+=8;} +else if (calc >= 4){calc-=4; pc1APP_ST+=4;} +else {pc1ADRCHK = calc; i=1;} +} +} +/**************************************************************** +*FUNCTION NAME:Split PKTCTRL0 +*FUNCTION :none +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::Split_PKTCTRL0(void){ +int calc = SpiReadStatus(8); +pc0WDATA = 0; +pc0PktForm = 0; +pc0CRC_EN = 0; +pc0LenConf = 0; +for (bool i = 0; i==0;){ +if (calc >= 64){calc-=64; pc0WDATA+=64;} +else if (calc >= 16){calc-=16; pc0PktForm+=16;} +else if (calc >= 4){calc-=4; pc0CRC_EN+=4;} +else {pc0LenConf = calc; i=1;} +} +} +/**************************************************************** +*FUNCTION NAME:Split MDMCFG1 +*FUNCTION :none +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::Split_MDMCFG1(void){ +int calc = SpiReadStatus(19); +m1FEC = 0; +m1PRE = 0; +m1CHSP = 0; +int s2 = 0; +for (bool i = 0; i==0;){ +if (calc >= 128){calc-=128; m1FEC+=128;} +else if (calc >= 16){calc-=16; m1PRE+=16;} +else {m1CHSP = calc; i=1;} +} +} +/**************************************************************** +*FUNCTION NAME:Split MDMCFG2 +*FUNCTION :none +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::Split_MDMCFG2(void){ +int calc = SpiReadStatus(18); +m2DCOFF = 0; +m2MODFM = 0; +m2MANCH = 0; +m2SYNCM = 0; +for (bool i = 0; i==0;){ +if (calc >= 128){calc-=128; m2DCOFF+=128;} +else if (calc >= 16){calc-=16; m2MODFM+=16;} +else if (calc >= 8){calc-=8; m2MANCH+=8;} +else{m2SYNCM = calc; i=1;} +} +} +/**************************************************************** +*FUNCTION NAME:Split MDMCFG4 +*FUNCTION :none +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::Split_MDMCFG4(void){ +int calc = SpiReadStatus(16); +m4RxBw = 0; +m4DaRa = 0; +for (bool i = 0; i==0;){ +if (calc >= 64){calc-=64; m4RxBw+=64;} +else if (calc >= 16){calc -= 16; m4RxBw+=16;} +else{m4DaRa = calc; i=1;} +} +} +/**************************************************************** +*FUNCTION NAME:RegConfigSettings +*FUNCTION :CC1101 register config //details refer datasheet of CC1101/CC1100// +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::RegConfigSettings(void) +{ + SpiWriteReg(CC1101_FSCTRL1, 0x06); + + setCCMode(ccmode); + setMHZ(MHz); + + SpiWriteReg(CC1101_MDMCFG1, 0x02); + SpiWriteReg(CC1101_MDMCFG0, 0xF8); + SpiWriteReg(CC1101_CHANNR, chan); + SpiWriteReg(CC1101_DEVIATN, 0x47); + SpiWriteReg(CC1101_FREND1, 0x56); + SpiWriteReg(CC1101_MCSM0 , 0x18); + SpiWriteReg(CC1101_FOCCFG, 0x16); + SpiWriteReg(CC1101_BSCFG, 0x1C); + SpiWriteReg(CC1101_AGCCTRL2, 0xC7); + SpiWriteReg(CC1101_AGCCTRL1, 0x00); + SpiWriteReg(CC1101_AGCCTRL0, 0xB2); + SpiWriteReg(CC1101_FSCAL3, 0xE9); + SpiWriteReg(CC1101_FSCAL2, 0x2A); + SpiWriteReg(CC1101_FSCAL1, 0x00); + SpiWriteReg(CC1101_FSCAL0, 0x1F); + SpiWriteReg(CC1101_FSTEST, 0x59); + SpiWriteReg(CC1101_TEST2, 0x81); + SpiWriteReg(CC1101_TEST1, 0x35); + SpiWriteReg(CC1101_TEST0, 0x09); + SpiWriteReg(CC1101_PKTCTRL1, 0x04); + SpiWriteReg(CC1101_ADDR, 0x00); + SpiWriteReg(CC1101_PKTLEN, 0x00); +} +/**************************************************************** +*FUNCTION NAME:SetTx +*FUNCTION :set CC1101 send data +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::SetTx(void) +{ + SpiStrobe(CC1101_SIDLE); + SpiStrobe(CC1101_STX); //start send + trxstate=1; +} +/**************************************************************** +*FUNCTION NAME:SetRx +*FUNCTION :set CC1101 to receive state +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::SetRx(void) +{ + SpiStrobe(CC1101_SIDLE); + SpiStrobe(CC1101_SRX); //start receive + trxstate=2; +} +/**************************************************************** +*FUNCTION NAME:SetTx +*FUNCTION :set CC1101 send data and change frequency +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::SetTx(float mhz) +{ + SpiStrobe(CC1101_SIDLE); + setMHZ(mhz); + SpiStrobe(CC1101_STX); //start send + trxstate=1; +} +/**************************************************************** +*FUNCTION NAME:SetRx +*FUNCTION :set CC1101 to receive state and change frequency +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::SetRx(float mhz) +{ + SpiStrobe(CC1101_SIDLE); + setMHZ(mhz); + SpiStrobe(CC1101_SRX); //start receive + trxstate=2; +} +/**************************************************************** +*FUNCTION NAME:RSSI Level +*FUNCTION :Calculating the RSSI Level +*INPUT :none +*OUTPUT :none +****************************************************************/ +int ELECHOUSE_CC1101::getRssi(void) +{ +int rssi; +rssi=SpiReadStatus(CC1101_RSSI); +if (rssi >= 128){rssi = (rssi-256)/2-74;} +else{rssi = (rssi/2)-74;} +return rssi; +} +/**************************************************************** +*FUNCTION NAME:LQI Level +*FUNCTION :get Lqi state +*INPUT :none +*OUTPUT :none +****************************************************************/ +byte ELECHOUSE_CC1101::getLqi(void) +{ +byte lqi; +lqi=SpiReadStatus(CC1101_LQI); +return lqi; +} +/**************************************************************** +*FUNCTION NAME:SetSres +*FUNCTION :Reset CC1101 +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setSres(void) +{ + SpiStrobe(CC1101_SRES); + trxstate=0; +} +/**************************************************************** +*FUNCTION NAME:setSidle +*FUNCTION :set Rx / TX Off +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::setSidle(void) +{ + SpiStrobe(CC1101_SIDLE); + trxstate=0; +} +/**************************************************************** +*FUNCTION NAME:goSleep +*FUNCTION :set cc1101 Sleep on +*INPUT :none +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::goSleep(void){ + trxstate=0; + SpiStrobe(0x36);//Exit RX / TX, turn off frequency synthesizer and exit + SpiStrobe(0x39);//Enter power down mode when CSn goes high. +} +/**************************************************************** +*FUNCTION NAME:Char direct SendData +*FUNCTION :use CC1101 send data +*INPUT :txBuffer: data array to send; size: number of data to send, no more than 61 +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::SendData(char *txchar) +{ +int len = strlen(txchar); +byte chartobyte[len]; +for (int i = 0; i sync transmitted + while (digitalRead(GDO0)); // Wait for GDO0 to be cleared -> end of packet + SpiStrobe(CC1101_SFTX); //flush TXfifo + trxstate=1; +} +/**************************************************************** +*FUNCTION NAME:Char direct SendData +*FUNCTION :use CC1101 send data without GDO +*INPUT :txBuffer: data array to send; size: number of data to send, no more than 61 +*OUTPUT :none +****************************************************************/ +void ELECHOUSE_CC1101::SendData(char *txchar,int t) +{ +int len = strlen(txchar); +byte chartobyte[len]; +for (int i = 0; i + Version: November 12, 2010 + + This library is designed to use CC1101/CC1100 module on Arduino platform. + CC1101/CC1100 module is an useful wireless module.Using the functions of the + library, you can easily send and receive data by the CC1101/CC1100 module. + Just have fun! + For the details, please refer to the datasheet of CC1100/CC1101. +---------------------------------------------------------------------------------------------------------------- +cc1101 Driver for RC Switch. Mod by Little Satan. With permission to modify and publish Wilson Shen (ELECHOUSE). +---------------------------------------------------------------------------------------------------------------- +*/ +#ifndef ELECHOUSE_CC1101_SRC_DRV_h +#define ELECHOUSE_CC1101_SRC_DRV_h + +#include + +//***************************************CC1101 define**************************************************// +// CC1101 CONFIG REGSITER +#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 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. +#define CC1101_SFSTXON 0x31 // 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_SXOFF 0x32 // Turn off crystal oscillator. +#define CC1101_SCAL 0x33 // Calibrate frequency synthesizer and turn it off + // (enables quick start). +#define CC1101_SRX 0x34 // Enable RX. Perform calibration first if coming from IDLE and + // MCSM0.FS_AUTOCAL=1. +#define CC1101_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_SIDLE 0x36 // Exit RX / TX, turn off frequency synthesizer and exit + // Wake-On-Radio mode if applicable. +#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. +#define CC1101_SNOP 0x3D // No operation. May be used to pad strobe commands to two + // INT8Us for simpler software. +//CC1101 STATUS REGSITER +#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 + +//CC1101 PATABLE,TXFIFO,RXFIFO +#define CC1101_PATABLE 0x3E +#define CC1101_TXFIFO 0x3F +#define CC1101_RXFIFO 0x3F + +//************************************* class **************************************************// +class ELECHOUSE_CC1101 +{ +private: + void SpiStart(void); + void SpiEnd(void); + void GDO_Set (void); + void GDO0_Set (void); + void Reset (void); + void setSpi(void); + void RegConfigSettings(void); + void Calibrate(void); + void Split_PKTCTRL0(void); + void Split_PKTCTRL1(void); + void Split_MDMCFG1(void); + void Split_MDMCFG2(void); + void Split_MDMCFG4(void); +public: + void Init(void); + byte SpiReadStatus(byte addr); + void setSpiPin(byte sck, byte miso, byte mosi, byte ss); + void addSpiPin(byte sck, byte miso, byte mosi, byte ss, byte modul); + void setGDO(byte gdo0, byte gdo2); + void setGDO0(byte gdo0); + void addGDO(byte gdo0, byte gdo2, byte modul); + void addGDO0(byte gdo0, byte modul); + void setModul(byte modul); + void setCCMode(bool s); + void setModulation(byte m); + void setPA(int p); + void setMHZ(float mhz); + void setChannel(byte chnl); + void setChsp(float f); + void setRxBW(float f); + void setDRate(float d); + void setDeviation(float d); + void SetTx(void); + void SetRx(void); + void SetTx(float mhz); + void SetRx(float mhz); + int getRssi(void); + byte getLqi(void); + void setSres(void); + void setSidle(void); + void goSleep(void); + void SendData(byte *txBuffer, byte size); + void SendData(char *txchar); + void SendData(byte *txBuffer, byte size, int t); + void SendData(char *txchar, int t); + byte CheckReceiveFlag(void); + byte ReceiveData(byte *rxBuffer); + bool CheckCRC(void); + void SpiStrobe(byte strobe); + void SpiWriteReg(byte addr, byte value); + void SpiWriteBurstReg(byte addr, byte *buffer, byte num); + byte SpiReadReg(byte addr); + void SpiReadBurstReg(byte addr, byte *buffer, byte num); + void setClb(byte b, byte s, byte e); + bool getCC1101(void); + byte getMode(void); + void setSyncWord(byte sh, byte sl); + void setAddr(byte v); + void setWhiteData(bool v); + void setPktFormat(byte v); + void setCrc(bool v); + void setLengthConfig(byte v); + void setPacketLength(byte v); + void setDcFilterOff(bool v); + void setManchester(bool v); + void setSyncMode(byte v); + void setFEC(bool v); + void setPRE(byte v); + void setPQT(byte v); + void setCRC_AF(bool v); + void setAppendStatus(bool v); + void setAdrChk(byte v); + bool CheckRxFifo(int t); +}; + +extern ELECHOUSE_CC1101 ELECHOUSE_cc1101; + +#endif \ No newline at end of file diff --git a/firmware/badusb.cpp b/firmware/badusb.cpp new file mode 100644 index 0000000..18c501a --- /dev/null +++ b/firmware/badusb.cpp @@ -0,0 +1,56 @@ +#include +#include + +extern USBHIDKeyboard Keyboard; + +void runBadUSBDemo() +{ + delay(2000); + Keyboard.println(""); + Keyboard.println("#-FEATURES:"); + Keyboard.println("1- WIFI ATTACKS"); + Keyboard.println("2- BLE ATTACKS"); + Keyboard.println("3- BAD USB"); + Keyboard.println("4- NFC"); + Keyboard.println("5- INFRARED"); + Keyboard.println("6- SUB-GHZ"); + Keyboard.println("7- GPIO"); + Keyboard.println("8- APPS"); + Keyboard.println("9- SETTINGS"); + Keyboard.println("10- FILES"); + +} + +void runBadUSBOpenCMD() +{ + delay(2000); + Keyboard.println(""); + Keyboard.println("#-FEATURES:"); + Keyboard.println("1- WIFI ATTACKS"); + Keyboard.println("2- BLE ATTACKS"); + Keyboard.println("3- BAD USB"); + Keyboard.println("4- NFC"); + Keyboard.println("5- INFRARED"); + Keyboard.println("6- SUB-GHZ"); + Keyboard.println("7- GPIO"); + Keyboard.println("8- APPS"); + Keyboard.println("9- SETTINGS"); + Keyboard.println("10- FILES"); +} + +void runBadUSBRickroll() +{ + delay(2000); + Keyboard.println(""); + Keyboard.println("#-FEATURES:"); + Keyboard.println("1- WIFI ATTACKS"); + Keyboard.println("2- BLE ATTACKS"); + Keyboard.println("3- BAD USB"); + Keyboard.println("4- NFC"); + Keyboard.println("5- INFRARED"); + Keyboard.println("6- SUB-GHZ"); + Keyboard.println("7- GPIO"); + Keyboard.println("8- APPS"); + Keyboard.println("9- SETTINGS"); + Keyboard.println("10- FILES"); +} diff --git a/firmware/badusb.h b/firmware/badusb.h new file mode 100644 index 0000000..a5a0dd5 --- /dev/null +++ b/firmware/badusb.h @@ -0,0 +1,5 @@ +#pragma once + +void runBadUSBDemo(); +void runBadUSBOpenCMD(); +void runBadUSBRickroll(); diff --git a/firmware/blescanner.cpp b/firmware/blescanner.cpp new file mode 100644 index 0000000..6cca404 --- /dev/null +++ b/firmware/blescanner.cpp @@ -0,0 +1,211 @@ +#include +#include +#include +#include +#include + +#include "display.h" +#include "buttons.h" +#include "config.h" + +// ===== DEVICE STRUCT ===== +struct BLEDeviceInfo { + String name; + String address; + int rssi; + String manufacturer; + String deviceType; +}; + +static std::vector devices; +static BLEScan *pBLEScan; +static int selectedIndex = 0; + +// ===== CALLBACK ===== +class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks { + void onResult(BLEAdvertisedDevice advertisedDevice) override { + BLEDeviceInfo dev; + + String tempName = advertisedDevice.getName(); + + if (tempName.length() == 0 && advertisedDevice.haveServiceData()) { + tempName = advertisedDevice.getServiceData().c_str(); + } + + if (tempName.length() == 0) { + String addr = advertisedDevice.getAddress().toString().c_str(); + tempName = "BLE_" + addr.substring(addr.length() - 5); + } + + dev.name = tempName; + dev.address = advertisedDevice.getAddress().toString().c_str(); + dev.rssi = advertisedDevice.getRSSI(); + + if (advertisedDevice.haveManufacturerData()) { + String mData = advertisedDevice.getManufacturerData().c_str(); + + if (mData.length() >= 2) { + char buffer[10]; + sprintf(buffer, "0x%02X%02X", + (uint8_t)mData[1], + (uint8_t)mData[0]); + dev.manufacturer = String(buffer); + } else { + dev.manufacturer = "unknown"; + } + } else { + dev.manufacturer = "unknown"; + } + + if (advertisedDevice.haveServiceUUID()) { + dev.deviceType = + advertisedDevice.getServiceUUID().toString().c_str(); + } else { + dev.deviceType = "unknown"; + } + + devices.push_back(dev); + } +}; + +// ===== DRAW MENU ===== +void ble_drawMenu() +{ + u8g2.clearBuffer(); + + if (devices.empty()) + { + u8g2.setFont(u8g2_font_6x12_tr); + u8g2.drawStr(0, 30, "No devices"); + u8g2.drawStr(0, 45, "Press BACK"); + } + else + { + u8g2.setFont(u8g2_font_5x8_tr); + + char counter[20]; + sprintf(counter, "%d/%d", selectedIndex + 1, (int)devices.size()); + u8g2.drawStr(0, 8, counter); + + u8g2.setFont(u8g2_font_6x10_tr); + + for (int i = 0; i < 3; i++) + { + int idx = selectedIndex + i; + if (idx >= devices.size()) break; + + int y = 22 + i * 14; + + if (i == 0) + { + u8g2.drawBox(0, y - 10, 128, 12); + u8g2.setDrawColor(0); + } + + String text = devices[idx].name; + if (text.length() > 12) + text = text.substring(0, 12) + ".."; + + text += " (" + String(devices[idx].rssi) + ")"; + + u8g2.drawStr(2, y, text.c_str()); + + if (i == 0) + u8g2.setDrawColor(1); + } + } + + u8g2.sendBuffer(); +} + +// ===== DEVICE DETAILS ===== +void ble_drawDetails(const BLEDeviceInfo &dev) +{ + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_5x8_tr); + + u8g2.drawStr(0, 10, dev.name.c_str()); + u8g2.drawStr(0, 20, dev.address.c_str()); + + char rssiStr[20]; + sprintf(rssiStr, "RSSI: %d", dev.rssi); + u8g2.drawStr(0, 30, rssiStr); + + u8g2.drawStr(0, 40, dev.manufacturer.c_str()); + + u8g2.sendBuffer(); +} + +// ===== SCAN ===== +void ble_scan() +{ + devices.clear(); + + u8g2.clearBuffer(); + u8g2.drawStr(10, 30, "Scanning..."); + u8g2.sendBuffer(); + + BLEDevice::init(""); + + pBLEScan = BLEDevice::getScan(); + pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks(), false); + pBLEScan->setActiveScan(true); + pBLEScan->setInterval(100); + pBLEScan->setWindow(99); + + pBLEScan->start(5, false); + + // remove duplicates + std::vector unique; + for (auto &d : devices) + { + bool exists = false; + for (auto &u : unique) + { + if (u.address == d.address) + { + exists = true; + break; + } + } + if (!exists) unique.push_back(d); + } + + devices = unique; +} + +// ===== MAIN LOOP ===== +void ble_loop() +{ + static uint32_t lastPress = 0; + + if (millis() - lastPress < 200) + return; + + if (btnDown() && selectedIndex < (int)devices.size() - 1) + { + selectedIndex++; + ble_drawMenu(); + lastPress = millis(); + } + else if (btnUp() && selectedIndex > 0) + { + selectedIndex--; + ble_drawMenu(); + lastPress = millis(); + } + else if (btnSelect() && !devices.empty()) + { + ble_drawDetails(devices[selectedIndex]); + delay(3000); + ble_drawMenu(); + lastPress = millis(); + } + else if (btnBack()) + { + ble_scan(); + selectedIndex = 0; + ble_drawMenu(); + lastPress = millis(); + } +} diff --git a/firmware/blescanner.h b/firmware/blescanner.h new file mode 100644 index 0000000..a642de2 --- /dev/null +++ b/firmware/blescanner.h @@ -0,0 +1,5 @@ +#pragma once + +void ble_scan(); +void ble_loop(); +void ble_drawMenu(); diff --git a/firmware/buttons.cpp b/firmware/buttons.cpp new file mode 100644 index 0000000..d28c4cc --- /dev/null +++ b/firmware/buttons.cpp @@ -0,0 +1,20 @@ +#include "buttons.h" +#include + +#define BTN_UP 4 +#define BTN_DOWN 5 +#define BTN_SELECT 6 +#define BTN_BACK 7 + +void buttonsInit() +{ + pinMode(BTN_UP, INPUT_PULLUP); + pinMode(BTN_DOWN, INPUT_PULLUP); + pinMode(BTN_SELECT, INPUT_PULLUP); + pinMode(BTN_BACK, INPUT_PULLUP); +} + +bool btnUp() { return !digitalRead(BTN_UP); } +bool btnDown() { return !digitalRead(BTN_DOWN); } +bool btnSelect() { return !digitalRead(BTN_SELECT); } +bool btnBack() { return !digitalRead(BTN_BACK); } diff --git a/firmware/buttons.h b/firmware/buttons.h new file mode 100644 index 0000000..077f35f --- /dev/null +++ b/firmware/buttons.h @@ -0,0 +1,8 @@ +#pragma once + +void buttonsInit(); + +bool btnUp(); +bool btnDown(); +bool btnSelect(); +bool btnBack(); diff --git a/firmware/cc1101.cpp b/firmware/cc1101.cpp new file mode 100644 index 0000000..dcbbbee --- /dev/null +++ b/firmware/cc1101.cpp @@ -0,0 +1,150 @@ +#include +#include "ELECHOUSE_CC1101_SRC_DRV.h" +#include "cc1101.h" +#include "config.h" + +// ===== CONFIG ===== +#define RAW_BUF_MAX 512 + +// ===== STATE ===== +static bool cc1101Inited = false; + +// ===== CAPTURE STATE ===== +volatile unsigned long captureBuffer[RAW_BUF_MAX]; +volatile int pulseIndex = 0; +volatile unsigned long lastEdgeTime = 0; +volatile bool capturing = false; + +// ===== RF SETTINGS ===== +float currentFreq = 433.92; +float dataRate = 3.79372; +float deviation = 0.0; +float rxBW = 325.0; +int powerLevel = 10; + +// ===== ISR ===== +void IRAM_ATTR pulseISR() +{ + unsigned long now = micros(); + + if (!capturing) return; + if (pulseIndex >= RAW_BUF_MAX) return; + + unsigned long duration = now - lastEdgeTime; + + if (duration < 50) return; + + captureBuffer[pulseIndex++] = duration; + lastEdgeTime = now; +} + +// ===== OOK SETUP ===== +void setupOOKMode() +{ + ELECHOUSE_cc1101.SetRx(); + ELECHOUSE_cc1101.setMHZ(currentFreq); + + ELECHOUSE_cc1101.setModulation(0); // ASK/OOK + ELECHOUSE_cc1101.setDRate(dataRate); + ELECHOUSE_cc1101.setDeviation(0); + ELECHOUSE_cc1101.setRxBW(rxBW); + ELECHOUSE_cc1101.setSyncMode(0); + ELECHOUSE_cc1101.setPA(powerLevel); +} + +// ===== INIT (LAZY, SAFE) ===== +bool initCC1101() +{ + if (cc1101Inited) + return true; + + Serial.println("Initializing CC1101..."); + + // IMPORTANT: no detachInterrupt here (causes crash if not installed) + + ELECHOUSE_cc1101.setSpiPin( + cc1101_SCK, + cc1101_MISO, + cc1101_MOSI, + CC1101_CS + ); + + ELECHOUSE_cc1101.setGDO(CC1101_GDO0, CC1101_GDO2); + + if (!ELECHOUSE_cc1101.getCC1101()) + { + Serial.println("❌ CC1101 NOT FOUND"); + return false; + } + + delay(10); // let SPI settle + + ELECHOUSE_cc1101.Init(); // THIS WAS YOUR FREEZE POINT + setupOOKMode(); + + pinMode(CC1101_GDO0, INPUT); + + Serial.println("✅ CC1101 READY"); + + cc1101Inited = true; + return true; +} + +// ===== CAPTURE CONTROL ===== +void startCapture() +{ + pulseIndex = 0; + capturing = true; + lastEdgeTime = micros(); + + attachInterrupt( + digitalPinToInterrupt(CC1101_GDO0), + pulseISR, + CHANGE + ); + + Serial.println("Capture started"); +} + +bool isCC1101Ready() { + return cc1101Inited; +} + +void stopCapture() +{ + capturing = false; + + detachInterrupt(digitalPinToInterrupt(CC1101_GDO0)); + + Serial.println("Capture stopped"); +} + +// ===== DEBUG PRINT ===== +void printCapture() +{ + Serial.println("Captured pulses:"); + + for (int i = 0; i < pulseIndex; i++) + { + Serial.println(captureBuffer[i]); + } +} + + +// ===== REPLAY ===== +void replaySignal() +{ + Serial.println("Replaying..."); + + ELECHOUSE_cc1101.SetTx(); + pinMode(CC1101_GDO0, OUTPUT); + + for (int i = 0; i < pulseIndex; i++) + { + digitalWrite(CC1101_GDO0, (i % 2 == 0) ? HIGH : LOW); + delayMicroseconds(captureBuffer[i]); + } + + digitalWrite(CC1101_GDO0, LOW); + ELECHOUSE_cc1101.SetRx(); +} diff --git a/firmware/cc1101.h b/firmware/cc1101.h new file mode 100644 index 0000000..a403edb --- /dev/null +++ b/firmware/cc1101.h @@ -0,0 +1,9 @@ +#pragma once + +bool initCC1101(); +bool isCC1101Ready(); + +void startCapture(); +void stopCapture(); +void printCapture(); +void replaySignal(); diff --git a/firmware/config.h b/firmware/config.h new file mode 100644 index 0000000..ce40ebc --- /dev/null +++ b/firmware/config.h @@ -0,0 +1,48 @@ +#pragma once + +// ================= NRF24 ================= +#define CE1_PIN 10 +#define CSN1_PIN 11 + +#define CE2_PIN 12 +#define CSN2_PIN 13 + +#define NRF_SCK 18 +#define NRF_MISO 16 +#define NRF_MOSI 17 + +// ================== OLED =================== +#define OLED_SDA_PIN 8 +#define OLED_SCL_PIN 9 + +/////////////////cc1101 vars////////////// +// CC1101 via FSPI +#define cc1101_SCK 15 +#define cc1101_MISO 3 +#define cc1101_MOSI 46 + +//////////////cc1101(1)////////// +#define CC1101_CS 45 +#define CC1101_GDO0 21 +#define CC1101_GDO2 47 + +/////////////cc1101(2)////////// +#define CC1101_2_CS 40 +#define CC1101_2_GDO0 41 +#define CC1101_2_GDO2 42 + +// SD Card via HSPI +#define SD_SCK 14 +#define SD_MISO 39 +#define SD_MOSI 38 +#define SD_CS 37 + + +// =================== Buttons ==================== +#define BTN_UP 4 +#define BTN_DOWN 5 +#define BTN_SELECT 6 +#define BTN_BACK 7 +#define BTN_LEFT 1 +#define BTN_RIGHT 2 + diff --git a/firmware/data/ESP32-BLE-Mouse.zip b/firmware/data/ESP32-BLE-Mouse.zip new file mode 100644 index 0000000..43e49f4 Binary files /dev/null and b/firmware/data/ESP32-BLE-Mouse.zip differ diff --git a/firmware/device_check.cpp b/firmware/device_check.cpp new file mode 100644 index 0000000..e09a76c --- /dev/null +++ b/firmware/device_check.cpp @@ -0,0 +1,242 @@ +#include +#include +#include +#include +#include "ELECHOUSE_CC1101_SRC_DRV.h" + +#include "display.h" +#include "buttons.h" +#include "config.h" + +// ===== EXTERNALS ===== +extern RF24 radio1; +extern RF24 radio2; +extern SPIClass *RADIO_SPI; +extern U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2; + +// ===== RESULTS ===== +struct DeviceStatus { + bool nrf_link = false; + bool nrf1 = false; + bool nrf2 = false; + bool cc1101 = false; + bool oled = true; + bool buttons = false; +}; + +// ===== NRF CHECK ===== +bool checkNRF(RF24 &radio) +{ + // safer: only init if needed + if (!radio.isChipConnected()) { + if (!radio.begin(RADIO_SPI)) + return false; + } + + return radio.isChipConnected(); +} + +// ===== CC1101 CHECK ===== +bool checkCC1101() +{ + ELECHOUSE_cc1101.setSpiPin( + cc1101_SCK, + cc1101_MISO, + cc1101_MOSI, + CC1101_CS + ); + + delay(5); // important stabilization + + return ELECHOUSE_cc1101.getCC1101(); +} + +// ===== BUTTON CHECK ===== +bool checkButtons() +{ + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_6x10_tr); + u8g2.drawStr(0, 20, "Press any button..."); + u8g2.sendBuffer(); + + unsigned long start = millis(); + + while (millis() - start < 2000) + { + if (!digitalRead(BTN_UP) || + !digitalRead(BTN_DOWN) || + !digitalRead(BTN_SELECT) || + !digitalRead(BTN_BACK)) + { + return true; + } + } + + return false; +} + +// ===== DRAW ===== +#define MAX_ITEMS 6 +#define VISIBLE_ROWS 5 + +const char* labels[MAX_ITEMS] = { + "NRF1", + "NRF2", + "LINK", + "CC1101", + "BUTTONS", + "OLED" +}; + +bool values[MAX_ITEMS]; + +int selectedIndex = 0; +int offset = 0; + +void drawStatus(DeviceStatus &s) +{ + values[0] = s.nrf1; + values[1] = s.nrf2; + values[2] = s.nrf_link; + values[3] = s.cc1101; + values[4] = s.buttons; + values[5] = s.oled; + + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_6x10_tr); + + // scrolling logic + if (selectedIndex < offset) + offset = selectedIndex; + + if (selectedIndex >= offset + VISIBLE_ROWS) + offset = selectedIndex - VISIBLE_ROWS + 1; + + for (int i = 0; i < VISIBLE_ROWS; i++) + { + int item = offset + i; + if (item >= MAX_ITEMS) break; + + int y = 12 + i * 10; + + if (item == selectedIndex) + { + u8g2.drawBox(0, y - 9, 128, 10); + u8g2.setDrawColor(0); + } + + u8g2.drawStr(2, y, labels[item]); + + if (values[item]) + u8g2.drawStr(80, y, "OK"); + else + u8g2.drawStr(80, y, "FAIL"); + + if (item == selectedIndex) + u8g2.setDrawColor(1); + } + + u8g2.sendBuffer(); +} + +bool testNRFLink() +{ + const byte address[6] = "00001"; + uint8_t payload = 0xAB; + uint8_t received = 0; + + // --- init radios --- + if (!radio1.begin(RADIO_SPI)) return false; + if (!radio2.begin(RADIO_SPI)) return false; + + radio1.setPALevel(RF24_PA_LOW); + radio2.setPALevel(RF24_PA_LOW); + + radio1.setDataRate(RF24_1MBPS); + radio2.setDataRate(RF24_1MBPS); + + radio1.setChannel(100); + radio2.setChannel(100); + + radio1.setAutoAck(false); + radio2.setAutoAck(false); + + // --- configure pipes --- + radio1.openWritingPipe(address); + radio2.openReadingPipe(0, address); + + radio2.startListening(); + + delay(50); + + // --- send --- + radio1.stopListening(); + bool sent = radio1.write(&payload, sizeof(payload)); + + if (!sent) return false; + + // --- receive --- + unsigned long start = millis(); + + while (millis() - start < 200) + { + if (radio2.available()) + { + radio2.read(&received, sizeof(received)); + return (received == payload); + } + } + + return false; +} + +// ===== MAIN ===== +void device_check_run() +{ + DeviceStatus status; + + Serial.println("Running device diagnostics..."); + + // NRF + // NRF link test + status.nrf_link = testNRFLink(); + status.nrf1 = checkNRF(radio1); + status.nrf2 = checkNRF(radio2); + + // CC1101 + status.cc1101 = checkCC1101(); + + // Buttons + status.buttons = checkButtons(); + + drawStatus(status); + + Serial.println("Diagnostics complete"); + +while (1) +{ +drawStatus(status); + +if (btnUp()) +{ +selectedIndex--; +if (selectedIndex < 0) selectedIndex = MAX_ITEMS - 1; +delay(150); +} + +if (btnDown()) +{ +selectedIndex++; +if (selectedIndex >= MAX_ITEMS) selectedIndex = 0; +delay(150); +} + +if (btnBack()) +{ +delay(150); +break; +} +}} + + + diff --git a/firmware/device_check.h b/firmware/device_check.h new file mode 100644 index 0000000..3d6b250 --- /dev/null +++ b/firmware/device_check.h @@ -0,0 +1,3 @@ +#pragma once + +void device_check_run(); diff --git a/firmware/display.cpp b/firmware/display.cpp new file mode 100644 index 0000000..12c9ac9 --- /dev/null +++ b/firmware/display.cpp @@ -0,0 +1,16 @@ +#include "display.h" +#include +#include "config.h" + + +U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2( + U8G2_R0, + U8X8_PIN_NONE +); + +void displayInit() +{ + Wire.begin(OLED_SDA_PIN, OLED_SCL_PIN); + u8g2.begin(); + u8g2.setFont(u8g2_font_6x12_tr); +} diff --git a/firmware/display.h b/firmware/display.h new file mode 100644 index 0000000..0b48b75 --- /dev/null +++ b/firmware/display.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +extern U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2; + +void displayInit(); diff --git a/firmware/firmware.ino b/firmware/firmware.ino new file mode 100644 index 0000000..5b71a60 --- /dev/null +++ b/firmware/firmware.ino @@ -0,0 +1,128 @@ +#include +#include +#include + +#include +#include + +#include +#include + +#include "ELECHOUSE_CC1101_SRC_DRV.h" + +#include +#include + +#include +#include +#include +#include + + +#include "display.h" +#include "buttons.h" +#include "menu.h" + +#include "config.h" +#include "cc1101.h" + +// ================= USB HID ================= +USBHIDKeyboard Keyboard; + + +RF24 radio1(CE1_PIN, CSN1_PIN); +RF24 radio2(CE2_PIN, CSN2_PIN); +SPIClass *RADIO_SPI; + + + + +// ================= BLE SCAN ================= +BLEScan *pBLEScan; + + +void startBLEScan() +{ + BLEDevice::init(""); + + pBLEScan = BLEDevice::getScan(); + + pBLEScan->setActiveScan(true); + + pBLEScan->start(5); + + Serial.println("BLE scan complete"); +} + +// ================= SYSTEM INFO ================= +void printSystemUsage() +{ + esp_chip_info_t chip_info; + + esp_chip_info(&chip_info); + + Serial.printf("CPU cores: %d\n", chip_info.cores); + + Serial.printf( + "Free heap: %d bytes\n", + heap_caps_get_free_size(MALLOC_CAP_DEFAULT) + ); + + Serial.printf( + "PSRAM free: %d bytes\n", + heap_caps_get_free_size(MALLOC_CAP_SPIRAM) + ); +} + +void showSplash() +{ + u8g2.clearBuffer(); + + u8g2.setFont(u8g2_font_logisoso20_tr); // big font + u8g2.drawStr(10, 40, "Orion-RF"); + + u8g2.setFont(u8g2_font_5x8_tr); // small subtitle + u8g2.drawStr(25, 58, "Initializing..."); + + u8g2.sendBuffer(); + + delay(1500); // 1.5 sec +} + + +// ================= SETUP ================= +void setup() +{ + Serial.begin(115200); + + displayInit(); + showSplash(); + + buttonsInit(); + menuInit(); + + delay(1500); + + USB.begin(); + Keyboard.begin(); + + // NRF SPI safety + pinMode(CSN1_PIN, OUTPUT); + digitalWrite(CSN1_PIN, HIGH); + + pinMode(CSN2_PIN, OUTPUT); + digitalWrite(CSN2_PIN, HIGH); + + RADIO_SPI = new SPIClass(FSPI); + RADIO_SPI->begin(NRF_SCK, NRF_MISO, NRF_MOSI); + + printSystemUsage(); + + Serial.println("SYSTEM READY"); +} + +// ================= LOOP ================= +void loop() +{ + menuLoop(); +} diff --git a/firmware/menu.cpp b/firmware/menu.cpp new file mode 100644 index 0000000..411df35 --- /dev/null +++ b/firmware/menu.cpp @@ -0,0 +1,278 @@ +#include +#include "menu.h" +#include "display.h" +#include "buttons.h" +#include "badusb.h" +#include "nrf24.h" +#include "cc1101.h" +#include "blescanner.h" +#include "wifi_scan.h" +#include "wifi_analyzer.h" +#include "device_check.h" + +// ================= FEATURE HANDLERS ================= +void runSystemInfoFeature(); +void runRFCaptureFeature(); +void runBLEScanFeature(); + + + +// ================= MENU DATA ================= + +// Root menu +const char *mainMenuItems[] = { + "BadUSB", + "RF Capture", + "NRF Jammer", + "BLE Scan", + "Wifi Scan", + "Wifi Analyzer", + "System Info", + "Device Check", + "Restart" +}; + +Menu mainMenu = {mainMenuItems, sizeof(mainMenuItems) / sizeof(mainMenuItems[0])}; + +// BadUSB submenu +const char *badusbItems[] = { + "Demo", + "Open CMD", + "Rickroll"}; + +Menu badusbMenu = {badusbItems, 3}; + +// ================= MENU STATE ================= + +Menu *currentMenu = &mainMenu; + +int menuIndex = 0; +int menuOffset = 0; + +#define MENU_VISIBLE_ROWS 4 + +bool insideFeature = false; + +// ================= DRAW ================= + +void drawMenu() +{ + u8g2.clearBuffer(); + + // scroll handling + if (menuIndex < menuOffset) + menuOffset = menuIndex; + + if (menuIndex >= menuOffset + MENU_VISIBLE_ROWS) + menuOffset = menuIndex - MENU_VISIBLE_ROWS + 1; + + for (int i = 0; i < MENU_VISIBLE_ROWS; i++) + { + int item = menuOffset + i; + + if (item >= currentMenu->size) + break; + + if (item == menuIndex) + u8g2.drawStr(0, 14 + i * 14, ">"); + + u8g2.drawStr(10, 14 + i * 14, currentMenu->items[item]); + } + + // scroll indicators + if (menuOffset > 0) + u8g2.drawStr(118, 10, "^"); + + if (menuOffset + MENU_VISIBLE_ROWS < currentMenu->size) + u8g2.drawStr(118, 62, "v"); + + u8g2.sendBuffer(); +} + +// ================= FEATURE EXECUTION ================= + +void launchFeature() +{ + insideFeature = true; + + if (currentMenu == &mainMenu) + { + switch (menuIndex) + { + case 0: // BadUSB → enter submenu + currentMenu = &badusbMenu; + menuIndex = 0; + menuOffset = 0; + break; + + case 1: + if (!isCC1101Ready()) { + if (!initCC1101()) { + Serial.println("CC1101 failed"); + return; + } + } + + Serial.println("Ready to capture..."); + + startCapture(); + delay(5000); + stopCapture(); + printCapture(); + break; + case 2: + startNRFJammer(); + break; + + case 3: + ble_scan(); + ble_drawMenu(); + while (1) { + ble_loop(); + if (btnBack()) + break; + } + break; + + case 4: + { + // Start scan once + wifi_scan_start(); + wifi_scan_draw(); + + while (1) { + wifi_scan_loop(); + // EXIT condition handled ONLY here + if (btnBack()) { + delay(150); // debounce + break; + } + } + break; + } + case 5: + { + + wifi_analyzer_start(); + + bool prevBack = false; + while (1) + { + wifi_analyzer_loop(); + bool nowBack = btnBack(); + if (nowBack && !prevBack) + { + delay(150); + break; + } + prevBack = nowBack; + } + break; + } + + case 6: + runSystemInfoFeature(); + break; + case 7: + device_check_run(); + break; + case 8: + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_6x13_tr); + u8g2.drawStr(30, 30, "Restarting..."); + u8g2.sendBuffer(); + delay(1000); + ESP.restart(); + break; + } + } + else if (currentMenu == &badusbMenu) + { + switch (menuIndex) + { + case 0: + runBadUSBDemo(); + break; + + case 1: + Serial.println("Open CMD payload"); + runBadUSBOpenCMD(); + break; + + case 2: + Serial.println("Rickroll payload"); + runBadUSBRickroll(); + break; + } + } + + insideFeature = false; + + drawMenu(); +} + +// ================= INIT ================= + +void menuInit() +{ + currentMenu = &mainMenu; + menuIndex = 0; + menuOffset = 0; + + drawMenu(); +} + +// ================= LOOP ================= + +void menuLoop() +{ + static uint32_t lastPress = 0; + + if (insideFeature) + return; + + if (millis() - lastPress < 150) + return; + + if (btnUp()) + { + menuIndex--; + + if (menuIndex < 0) + menuIndex = currentMenu->size - 1; + + drawMenu(); + lastPress = millis(); + } + + else if (btnDown()) + { + menuIndex++; + + if (menuIndex >= currentMenu->size) + menuIndex = 0; + + drawMenu(); + lastPress = millis(); + } + + else if (btnSelect()) + { + launchFeature(); + lastPress = millis(); + } + + else if (btnBack()) + { + if (currentMenu != &mainMenu) + { + currentMenu = &mainMenu; + menuIndex = 0; + menuOffset = 0; + + drawMenu(); + } + + lastPress = millis(); + } +} diff --git a/firmware/menu.h b/firmware/menu.h new file mode 100644 index 0000000..c51cd24 --- /dev/null +++ b/firmware/menu.h @@ -0,0 +1,10 @@ +#pragma once + +struct Menu +{ + const char **items; + int size; +}; + +void menuInit(); +void menuLoop(); diff --git a/firmware/nrf24.cpp b/firmware/nrf24.cpp new file mode 100644 index 0000000..8c1b4d9 --- /dev/null +++ b/firmware/nrf24.cpp @@ -0,0 +1,99 @@ +#include +#include +#include "buttons.h" +#include "nrf24.h" +#include "display.h" +#define JAM_DURATION 500 + +extern SPIClass *RADIO_SPI; +extern RF24 radio1; +extern RF24 radio2; + +void initNRF(RF24 &radio) +{ + radio.begin(RADIO_SPI); + + radio.setAutoAck(false); + radio.stopListening(); + + radio.setRetries(0, 0); + radio.setDataRate(RF24_2MBPS); +radio.setPALevel(RF24_PA_MAX); + + radio.openWritingPipe(0xE7E7E7E7E7LL); +} + + +void jamChannels(const char* label, int startCh, int endCh) { + byte data1[32], data2[32]; + for (int i = 0; i < 32; i++) { + data1[i] = random(0, 256); + data2[i] = random(0, 256); + } + + for (int ch = startCh; ch <= endCh; ch++) { + // Status screen + u8g2.clearBuffer(); + u8g2.drawStr(0, 10, "Jamming:"); + u8g2.setCursor(60, 10); + u8g2.print(label); + u8g2.setCursor(0, 30); + u8g2.print("Channel: "); + u8g2.print(ch); + u8g2.sendBuffer(); + + unsigned long startTime = millis(); + while (millis() - startTime < JAM_DURATION) { + radio1.setChannel(ch); + radio1.stopListening(); + radio1.write(data1, sizeof(data1)); + delayMicroseconds(100); + + radio2.setChannel(ch); + radio2.stopListening(); + radio2.write(data2, sizeof(data2)); + delayMicroseconds(100); + + } +} +} + + +void nrfJammerSweep() +{ + static uint8_t ch1 = 0; + static uint8_t ch2 = 124; + + uint8_t payload[32] = {0xFF}; + + radio1.setChannel(ch1); + radio1.writeFast(payload, sizeof(payload)); + + radio2.setChannel(ch2); + radio2.writeFast(payload, sizeof(payload)); + + ch1++; + ch2--; + + if (ch1 > 124) ch1 = 0; + if (ch2 > 124) ch2 = 124; +} + +void startNRFJammer() +{ + initNRF(radio1); + initNRF(radio2); + + Serial.println("NRF JAMMER STARTED"); + // nrfJammerSweep(); + jamChannels("Bluetooth", 0, 78); + + + if (btnBack()) + { + Serial.println("Jammer stopped"); + return; + } + + delayMicroseconds(200); +} diff --git a/firmware/nrf24.h b/firmware/nrf24.h new file mode 100644 index 0000000..9d543fc --- /dev/null +++ b/firmware/nrf24.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +// Initialization +void initNRF(RF24 &radio); + +// Jammer modes +void startNRFJammer(); // dual-radio sweep jammer +void stopNRFJammer(); // (optional, for future) + +// Advanced (later) +void nrfJammerSweep(); // internal, but can expose if needed +void nrfSetChannel(uint8_t ch); diff --git a/firmware/stubs.cpp b/firmware/stubs.cpp new file mode 100644 index 0000000..c7782ca --- /dev/null +++ b/firmware/stubs.cpp @@ -0,0 +1,13 @@ +#include + + +void runRFCaptureFeature() +{ + Serial.println("RF Capture not implemented yet"); +} + + +void runBLEScanFeature() +{ + Serial.println("BLE Scan not implemented yet"); +} diff --git a/firmware/sysinfo.cpp b/firmware/sysinfo.cpp new file mode 100644 index 0000000..afd13aa --- /dev/null +++ b/firmware/sysinfo.cpp @@ -0,0 +1,87 @@ +#include +#include "display.h" +#include "buttons.h" +#include +#include + +void runSystemInfoFeature() +{ + esp_chip_info_t chip_info; + + esp_chip_info(&chip_info); + + while (true) + { + //u8g2.clearBuffer(); + + //char buf[32]; + + //sprintf(buf, "Cores: %d", chip_info.cores); + //u8g2.drawStr(0, 14, buf); + + //sprintf(buf, "Heap: %d", + // heap_caps_get_free_size(MALLOC_CAP_DEFAULT)); + //u8g2.drawStr(0, 28, buf); + + + //u8g2.drawStr(0, 60, "BACK to exit"); + + // Get RAM info + size_t freeHeap = heap_caps_get_free_size(MALLOC_CAP_DEFAULT); + size_t totalHeap = heap_caps_get_total_size(MALLOC_CAP_DEFAULT); + int ramUsage = 100 - ((freeHeap * 100) / totalHeap); + + // Get Flash info + //uint32_t flashSize = spi_flash_get_chip_size(); + uint32_t flashSize = ESP.getFlashChipSize(); + uint32_t flashUsed = ESP.getSketchSize(); + int flashUsage = (flashUsed * 100) / flashSize; + + // Temperature (approx) + uint8_t temperature = temperatureRead(); + + // Chip info + esp_chip_info_t chip_info; + esp_chip_info(&chip_info); + + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_6x12_tr); + + char buf[32]; + + // Box 1 - RAM + u8g2.drawFrame(0, 0, 128, 12); + sprintf(buf, "RAM: %d%% used", ramUsage); + u8g2.drawStr(4, 9, buf); + + // Box 2 - Flash + u8g2.drawFrame(0, 12, 128, 12); + sprintf(buf, "Flash: %d%% used", flashUsage); + u8g2.drawStr(4, 21, buf); + + // Box 3 - Temp (FULL WIDTH now) + u8g2.drawFrame(0, 24, 128, 12); + sprintf(buf, "Temp: %d C", temperature); + u8g2.drawStr(4, 33, buf); + + // Box 4 - Chip info (FULL WIDTH) + u8g2.drawFrame(0, 36, 128, 12); + sprintf(buf, "Cores: %d Rev: %d", chip_info.cores, chip_info.revision); + u8g2.drawStr(4, 45, buf); + + // Box 5 - PSRAM (KB) + u8g2.drawFrame(0, 48, 128, 12); + sprintf(buf, "PSRAM: %lu KB", heap_caps_get_free_size(MALLOC_CAP_SPIRAM) / 1024); + u8g2.drawStr(4, 57, buf); + + u8g2.sendBuffer(); + + if (btnBack()) + { + delay(200); + return; + } + + delay(100); + } +} diff --git a/firmware/sysinfo.h b/firmware/sysinfo.h new file mode 100644 index 0000000..8a4f176 --- /dev/null +++ b/firmware/sysinfo.h @@ -0,0 +1,3 @@ +#pragma once + +void runSystemInfoFeature(); diff --git a/firmware/wifi_analyzer.cpp b/firmware/wifi_analyzer.cpp new file mode 100644 index 0000000..0264088 --- /dev/null +++ b/firmware/wifi_analyzer.cpp @@ -0,0 +1,147 @@ +#include +#include +#include + +#include "display.h" +#include "buttons.h" + +// ===== CONFIG ===== +#define GRAPH_WIDTH 128 +#define GRAPH_HEIGHT 44 +#define GRAPH_TOP 10 +#define MAX_POINTS 128 +#define SPIKE_THRESHOLD 30 + +// ===== STATE ===== +struct SnifferGraph { + uint8_t graphData[MAX_POINTS]; + uint8_t currentChannel = 1; + volatile uint16_t packetCounter = 0; + unsigned long lastChannelSwitch = 0; + unsigned long lastUpdate = 0; +}; + +static SnifferGraph sniffer; + +// ===== CALLBACK ===== +void IRAM_ATTR snifferCallback(void *buf, wifi_promiscuous_pkt_type_t type) +{ + if (type == WIFI_PKT_MGMT || type == WIFI_PKT_DATA || type == WIFI_PKT_CTRL) + { + sniffer.packetCounter++; + } +} + +// ===== INIT ===== +void wifi_analyzer_start() +{ + // display init (safe to call again) + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_5x8_tr); + u8g2.drawStr(0, 10, "Starting analyzer..."); + u8g2.sendBuffer(); + + // reset graph + memset(sniffer.graphData, 0, sizeof(sniffer.graphData)); + sniffer.packetCounter = 0; + sniffer.currentChannel = 1; + + // reset WiFi + WiFi.disconnect(true, true); + esp_wifi_stop(); + delay(200); + esp_wifi_deinit(); + + wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); + esp_wifi_init(&cfg); + esp_wifi_set_storage(WIFI_STORAGE_RAM); + esp_wifi_set_mode(WIFI_MODE_NULL); + esp_wifi_start(); + + esp_wifi_set_channel(sniffer.currentChannel, WIFI_SECOND_CHAN_NONE); + esp_wifi_set_promiscuous_rx_cb(snifferCallback); + esp_wifi_set_promiscuous(true); +} + +// ===== HELPERS ===== +static void switchChannel() +{ + sniffer.currentChannel++; + if (sniffer.currentChannel > 13) sniffer.currentChannel = 1; + + esp_wifi_set_channel(sniffer.currentChannel, WIFI_SECOND_CHAN_NONE); +} + +static void updateGraph(uint8_t value) +{ + for (int i = 0; i < MAX_POINTS - 1; i++) + { + sniffer.graphData[i] = sniffer.graphData[i + 1]; + } + + sniffer.graphData[MAX_POINTS - 1] = value; +} + +static void drawGraph(uint16_t pktCount) +{ + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_5x8_tr); + + char line1[16]; + char line2[16]; + + sprintf(line1, "Ch:%d", sniffer.currentChannel); + sprintf(line2, "Pkts:%d", pktCount * 5); + + u8g2.drawStr(0, 8, line1); + u8g2.drawStr(60, 8, line2); + + for (int x = 1; x < GRAPH_WIDTH; x++) + { + int y1 = GRAPH_TOP + GRAPH_HEIGHT - sniffer.graphData[x - 1]; + int y2 = GRAPH_TOP + GRAPH_HEIGHT - sniffer.graphData[x]; + + u8g2.drawLine(x - 1, y1, x, y2); + } + + if (pktCount >= SPIKE_THRESHOLD) + { + u8g2.drawVLine(GRAPH_WIDTH / 2, GRAPH_TOP, GRAPH_HEIGHT); + } + + u8g2.sendBuffer(); +} + +// ===== LOOP ===== +void wifi_analyzer_loop() +{ + static uint32_t lastPress = 0; + unsigned long now = millis(); + + // channel hopping + if (now - sniffer.lastChannelSwitch >= 1000) + { + sniffer.lastChannelSwitch = now; + switchChannel(); + } + + // graph update + if (now - sniffer.lastUpdate >= 200) + { + sniffer.lastUpdate = now; + + uint16_t pktCount = sniffer.packetCounter; + + uint8_t scaled = pktCount * 2; + uint8_t value = min(scaled, (uint8_t)GRAPH_HEIGHT); + + updateGraph(value); + drawGraph(pktCount); + + sniffer.packetCounter = 0; + } + + // optional: small debounce to not hammer CPU + if (millis() - lastPress < 10) + return; +} diff --git a/firmware/wifi_analyzer.h b/firmware/wifi_analyzer.h new file mode 100644 index 0000000..df68284 --- /dev/null +++ b/firmware/wifi_analyzer.h @@ -0,0 +1,4 @@ +#pragma once + +void wifi_analyzer_start(); +void wifi_analyzer_loop(); diff --git a/firmware/wifi_scan.cpp b/firmware/wifi_scan.cpp new file mode 100644 index 0000000..d4657bb --- /dev/null +++ b/firmware/wifi_scan.cpp @@ -0,0 +1,152 @@ +#include +#include +#include "display.h" +#include "buttons.h" + +#define MAX_NETWORKS 30 + +struct WiFiNet { + String ssid; + int rssi; + int channel; + bool encrypted; +}; + +static WiFiNet networks[MAX_NETWORKS]; +static int networkCount = 0; +static int selectedIndex = 0; + +// ===== SCAN ===== +void wifi_scan_start() +{ + u8g2.clearBuffer(); + u8g2.drawStr(10, 30, "Scanning WiFi..."); + u8g2.sendBuffer(); + + WiFi.mode(WIFI_STA); + WiFi.disconnect(); + + delay(100); + + int n = WiFi.scanNetworks(); + + networkCount = min(n, MAX_NETWORKS); + + for (int i = 0; i < networkCount; i++) + { + networks[i].ssid = WiFi.SSID(i); + networks[i].rssi = WiFi.RSSI(i); + networks[i].channel = WiFi.channel(i); + networks[i].encrypted = (WiFi.encryptionType(i) != WIFI_AUTH_OPEN); + } + + selectedIndex = 0; +} + +// ===== DRAW ===== +void wifi_scan_draw() +{ + u8g2.clearBuffer(); + + if (networkCount == 0) + { + u8g2.drawStr(0, 30, "No networks"); + u8g2.drawStr(0, 45, "Press BACK"); + } + else + { + char counter[20]; + sprintf(counter, "%d/%d", selectedIndex + 1, networkCount); + u8g2.setFont(u8g2_font_5x8_tr); + u8g2.drawStr(0, 8, counter); + + u8g2.setFont(u8g2_font_6x10_tr); + + for (int i = 0; i < 3; i++) + { + int idx = selectedIndex + i; + if (idx >= networkCount) break; + + int y = 22 + i * 14; + + if (i == 0) + { + u8g2.drawBox(0, y - 10, 128, 12); + u8g2.setDrawColor(0); + } + + String text = networks[idx].ssid; + if (text.length() > 10) + text = text.substring(0, 10) + ".."; + + text += " (" + String(networks[idx].rssi) + ")"; + + u8g2.drawStr(2, y, text.c_str()); + + if (i == 0) + u8g2.setDrawColor(1); + } + } + + u8g2.sendBuffer(); +} + +// ===== DETAILS ===== +void wifi_drawDetails() +{ + if (networkCount == 0) return; + + WiFiNet &net = networks[selectedIndex]; + + u8g2.clearBuffer(); + u8g2.setFont(u8g2_font_5x8_tr); + + u8g2.drawStr(0, 10, net.ssid.c_str()); + + char rssi[20]; + sprintf(rssi, "RSSI: %d", net.rssi); + u8g2.drawStr(0, 20, rssi); + + char ch[20]; + sprintf(ch, "CH: %d", net.channel); + u8g2.drawStr(0, 30, ch); + + u8g2.drawStr(0, 40, net.encrypted ? "Secured" : "Open"); + + u8g2.sendBuffer(); +} + +// ===== LOOP ===== +void wifi_scan_loop() +{ + static uint32_t lastPress = 0; + + if (millis() - lastPress < 150) + return; + + if (btnDown() && selectedIndex < networkCount - 1) + { + selectedIndex++; + wifi_scan_draw(); + lastPress = millis(); + } + else if (btnUp() && selectedIndex > 0) + { + selectedIndex--; + wifi_scan_draw(); + lastPress = millis(); + } + else if (btnSelect() && networkCount > 0) + { + wifi_drawDetails(); + delay(3000); + wifi_scan_draw(); + lastPress = millis(); + } +// else if (btnBack()) +// { +// wifi_scan_start(); +// wifi_scan_draw(); +// lastPress = millis(); +// } +} diff --git a/firmware/wifi_scan.h b/firmware/wifi_scan.h new file mode 100644 index 0000000..902054e --- /dev/null +++ b/firmware/wifi_scan.h @@ -0,0 +1,5 @@ +#pragma once + +void wifi_scan_start(); +void wifi_scan_loop(); +void wifi_scan_draw();