$(shell mkdir -p sim >/dev/null)
$(shell mkdir -p sim/build >/dev/null)
-NAME="test_2024-07-23_nano-644"
-SRC= $(wildcard src/*.c src/*.cpp src/*/*.cpp)
+NAME=test_2024-07-23_nano-644
+SRC= $(wildcard src/*.c src/*.cpp src/*/*.c src/*/*.cpp)
+HDR= $(wildcard src/*.h src/*.hpp src/*/*.h src/*/*.hpp)
OBJ_CPP = $(SRC:src/%.cpp=build/%.o)
OBJ = $(OBJ_CPP:src/%.c=build/%.o)
OBJ_SIM_CPP = $(SRC:src/%.cpp=sim/build/%.o)
all: dist/$(NAME).elf dist/$(NAME).s dist/$(NAME).hex sim/$(NAME).elf sim/$(NAME).s info
dbg:
- @echo "OBJ_CPP" $(OBJ_CPP)
- @echo "OBJ" $(OBJ)
- @echo "OBJ_SIM_CPP" $(OBJ_SIM_CPP)
- @echo "OBJ_SIM" $(OBJ_SIM)
+ @echo --HDR---------------------------------
+ @echo $(HDR)
+ @echo --SRC---------------------------------
+ @echo $(SRC)
+ @echo --OBJ---------------------------------
+ @echo $(OBJ)
+ @echo --OBJ_CPP-----------------------------
+ @echo $(OBJ_CPP)
+ @echo --OBJ---------------------------------
+ @echo $(OBJ)
+ @echo ===================================
+ @echo
info:
- @echo
@avr-size --mcu=$(DEVICE) --format=avr dist/$(NAME).elf
-.depend: $(SRC)
- $(CC) -MM $(SRC) > .depend
+.depend: $(SRC) $(HDR)
+ $(CC) -MM $(SRC) | sed --regexp-extended 's/^(.*\.o)\: src\/(.*)(\.cpp|\.c) (.*)/build\/\2\.o\: src\/\2\3 \4/g' > .depend
--include $(DEPENDFILE)
+-include .depend
+
+# .depend solte auch auf Header Files achten!
dist/$(NAME).elf: .depend $(OBJ)
$(CC) $(LFLAGS) -o $@ $(OBJ)
static FILE mystdout = { 0, 0, _FDEV_SETUP_WRITE , 0, 0, uart_putchar, NULL, 0 };
static FILE mystdin = { 0, 0, _FDEV_SETUP_READ , 0, 0, NULL, uart_getchar, 0 };
+ #ifdef __AVR_ATmega644P__
+ static volatile uint16_t timerFlashGreenLed = 0;
+ static volatile uint16_t timerFlashRedLed = 0;
+ void flashRedLed (uint16_t ms) {
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+ if (timerFlashRedLed == 0) {
+ PORTC |= (1 << PC2);
+ if (ms < 0xff80) {
+ ms += 0x80; // at least 128ms OFF after
+ }
+ timerFlashRedLed = ms;
+ }
+ }
+ }
+ void flashGreenLed (uint16_t ms) {
+ ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
+ if (timerFlashGreenLed == 0) {
+ PORTC |= (1 << PC4);
+ if (ms < 0xff80) {
+ ms += 0x80; // at least 128ms OFF after
+ }
+ timerFlashGreenLed = ms;
+ }
+ }
+ }
+ #endif
+
static volatile uint32_t timer1ms = 0;
static volatile int keyUart0 = EOF;
i2cSlave.tick1ms();
i2cSparkfun.tick1ms();
cc1101.tick1ms();
+ #ifdef __AVR_ATmega644P__
+ if (timerFlashRedLed > 0) {
+ if (--timerFlashRedLed < 128) {
+ PORTC &= ~(1 << PC2); // red LED
+ }
+ }
+ if (timerFlashGreenLed > 0) {
+ if (--timerFlashGreenLed < 128 ) {
+ PORTC &= ~(1 << PC4); // green LED
+ }
+ }
+ #endif
}
timer500ms++;
extern int wait (uint32_t ms);
extern uint64_t millis ();
+#ifdef __AVR_ATmega644P__
+ extern "C" {
+ extern void flashRedLed (uint16_t ms);
+ extern void flashGreenLed (uint16_t ms);
+ }
+#endif
+
+
class TestUnit {
public:
virtual int8_t run (uint8_t subtest) = 0;
+++ /dev/null
-#include <stdio.h>
-#include <avr/io.h>
-#include <avr/pgmspace.h>
-#include <util/delay.h>
-
-#include "cc1101.hpp"
-#include "../main.hpp"
-
-// 868MHz Modem E07-900MM1DS (chipset CC1101)
-// https://jlcpcb.com/partdetail/Chengdu_Ebyte_ElecTech-E07900MM10S/C5844212
-
-#ifdef __AVR_ATmega328P__
-
- // Arduino-Nano-5V
- // ------------------------------------
- // not available
-
- void PortExp::init () {}
- void PortExp::cleanup () {}
- void PortExp::setChipEnable () {}
- void PortExp::clearChipEnable () {}
-
-#endif
-
-
-#ifdef __AVR_ATmega644P__
-
- // Nano-644
- // --------------------------------------------------------
- // PA4 ... nCS
- // PB5 ... MOSI
- // PB6 ... MISO
- // PB7 ... SCK
-
-const uint8_t PMEM_CC1101_INIT[] PROGMEM = {
- CC1101_MDMCFG4, 0x5B, // modem config 4 -> ADC decimation rate, symbol rate exponent
- CC1101_MDMCFG3, 0xF8, // modem config 3 -> symbol rate mantissa
- CC1101_MDMCFG2, 0x03, // modem config 2 -> DC blocking filter, modulation type, manchaster enoding, sync-mode,
- CC1101_MDMCFG1, 0x22, // modem config 1 -> forw error correction, min number of preamble bytes, channel spacing exponent
- CC1101_MDMCFG0, 0xF8, // modem config 0 -> channel spacing mantissa
- CC1101_CHANNR, 0x00, // channel number
- CC1101_DEVIATN, 0x47, // modem deviation setting
- CC1101_FREND1, 0xB6, // front end RX configuration
- CC1101_FREND0, 0x10, // front end TX configuration
- CC1101_MCSM0 , 0x18, // Main Radio Control State Machine Configuration
- CC1101_FOCCFG, 0x1D, // Frequency Offset Compensation Configuration
- CC1101_BSCFG, 0x1C, // Bit Synchronization Configuration
- CC1101_AGCCTRL2, 0xC7, // AGC Control
- CC1101_AGCCTRL1, 0x00, // AGC Control
- CC1101_AGCCTRL0, 0xB2, // AGC Control
- CC1101_FSCAL3, 0xEA, // Frequency Synthesizer Calibration
- CC1101_FSCAL2, 0x2A, // Frequency Synthesizer Calibration
- CC1101_FSCAL1, 0x00, // Frequency Synthesizer Calibration
- CC1101_FSCAL0, 0x11, // Frequency Synthesizer Calibration
- // CC1101_FSTEST, 0x59, // Frequency Synthesizer Calibration Control
- // CC1101_TEST2, 0x81, // Various Test Settings
- // CC1101_TEST1, 0x35, // Various Test Settings
- // CC1101_TEST0, 0x09, // Various Test Settings
- CC1101_IOCFG2, 0x0B, // GDO2 Output Pin Configuration -> Serial Clock. Synchronous to the data in synchronous serial mode.
- CC1101_IOCFG0, 0x06, // GDO0 Output Pin Configuration -> Asserts when sync word has been sent / received, and de-asserts at the end of the packet.
- CC1101_PKTCTRL1, 0x04, // Packet Automation Control
- CC1101_PKTCTRL0, 0x05, // serial clock.synchronous to the data in synchronous serial mode
- CC1101_ADDR, 0x00, // asserts when sync word has been sent/received, and de-asserts at the end of the packet
- CC1101_PKTLEN, 0x3D, // two status bytes will be appended to the payload of the packet,including RSSI LQI and CRC OK
- CC1101_PKTCTRL0, 0x05, // whitening off; normal mode, CRC enabled, variable packet length
- CC1101_ADDR, 0x00, // address used for packet filtration.
- CC1101_PKTLEN, 0x3D // 61 bytes max length
-};
-
-
-const uint8_t PMEM_CC1101_PA_TABLE[8] PROGMEM = { 0x60 ,0x60 ,0x60 ,0x60 ,0x60 ,0x60 ,0x60 ,0x60 };
-
- void Cc1101::triggerOn () {
- PORTB |= (1 << PB0);
- }
-
- void Cc1101::triggerOff () {
- PORTB &= ~(1 << PB0);
- }
-
- void Cc1101::init () {
- // trigger for debugging
- PORTB &= ~(1 << PB0);
- DDRB |= ( 1 << PB0);
-
- PRR &= (1 << PRSPI);
- PORTA |= (1 << PA4);
- DDRA |= (1 << PA4); // SPI nCS
- // PORTB/DDRB must be configured before SPCR !!
- PORTB |= (1 << PB4); // nSS must be HIGH, otherwise SPI master will not become active!!
- DDRB &= ~(1 << PB6); // MISO
- DDRB |= (1 << PB7) | (1 << PB5) | (1 << PB4); // SPI SCK (=PB7) and SPI MOSI (=PB5)
-
- // SPCR |= (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); // SPI enable , Master, f=12MHz/128=93,75kHz
- SPCR = (1 << SPE) | (1 << MSTR); // SPI enable , Master, f=12MHz/4 = 3MHz
-
- // GDO0
- PORTA |= (1 << PA5);
- DDRA &= ~(1 << PA5);
- }
-
- void Cc1101::cleanup () {
- // trigger for debugging
- PORTB &= ~(1 << PB0);
- DDRB &= ~( 1 << PB0);
-
- SPCR = 0;
- DDRB &= ~((1 << PB7) | (1 << PB6) | (1 << PB5) | (1 << PB4));
- DDRA &= ~((1 << PA5) | (1 << PA4));
- PORTA &= ~((1 << PA5) | (1 << PA4));
- }
-
-
-
-
- void Cc1101::setChipEnableLow () {
- PORTA &= ~(1 << PA4);
- }
-
- void Cc1101::setChipEnableHigh () {
- PORTA |= (1 << PA4);
- }
-
- bool Cc1101::isMisoHigh () {
- return (PINB & (1 << PB6)) != 0;
- }
-
- bool Cc1101::isGd0High () {
- return (PINA & (1 << PA5)) != 0;
- }
-
-#endif
-
-uint8_t Cc1101::sendSpiByte (uint8_t b) {
- SPDR = b;
- while (!(SPSR & (1<<SPIF))) {}
- return SPDR;
-}
-
-bool Cc1101::waitForMisoLow () {
- timer = 10;
- while (isMisoHigh()) {
- if (timer == 0) {
- return false;
- }
- }
- return true;
-}
-
-bool Cc1101::waitForGD0High () {
- timer = 100;
- while (!isGd0High()) {
- if (timer == 0) {
- return false;
- }
- }
- return true;
-}
-
-bool Cc1101::waitForGD0Low () {
- return !waitForGD0High();
-}
-
-
-
-bool Cc1101::writeRegister (uint8_t addr, uint8_t value) {
- bool ok = true;
- timer = 10;
- setChipEnableLow();
- ok &= waitForMisoLow();
- sendSpiByte(addr);
- sendSpiByte(value);
- setChipEnableHigh();
- return ok;
-}
-
-bool Cc1101::writeRegisters (uint8_t addr, uint8_t *buffer, uint8_t length) {
- bool ok = true;
-
- addr |= WRITE_BURST;
- setChipEnableLow();
- ok &= waitForMisoLow();
- sendSpiByte(addr);
- while (length-- > 0) {
- sendSpiByte(*buffer++);
- }
- setChipEnableHigh();
- return ok;
-}
-
-bool Cc1101::strobe (uint8_t strobe) {
- bool ok = true;
- setChipEnableLow();
- ok &= waitForMisoLow();
- sendSpiByte(strobe);
- setChipEnableHigh();
- return ok;
-}
-
-
-bool Cc1101::readRegister (uint8_t addr, uint8_t *value) {
- bool ok = true;
-
- addr |= READ_SINGLE;
- setChipEnableLow();
- ok &= waitForMisoLow();
- sendSpiByte(addr);
- *value = sendSpiByte(0);
- setChipEnableHigh();
- return ok;
-}
-
-bool Cc1101::readRegisters (uint8_t addr, uint8_t *buffer, uint8_t length) {
- bool ok = true;
-
- addr |= READ_BURST;
- setChipEnableLow();
- ok &= waitForMisoLow();
- sendSpiByte(addr);
- while (length-- > 0) {
- *buffer++ = sendSpiByte(0);
- }
- setChipEnableHigh();
- return ok;
-}
-
-bool Cc1101::readStatus (uint8_t addr, uint8_t *status) {
- return readRegisters(addr, status, 1);
- // bool ok = true;
-
- // addr |= READ_BURST;
- // setChipEnableLow();
- // ok &= waitForMisoLow();
- // sendSpiByte(addr);
- // *status = sendSpiByte(0);
- // setChipEnableHigh();
- // return ok;
-}
-
-bool Cc1101::sendData (uint8_t *buffer, uint8_t length) {
- bool ok = true;
- ok &= writeRegister(CC1101_TXFIFO, length);
- ok &= writeRegisters(CC1101_TXFIFO, buffer, length);
- ok &= strobe(CC1101_STX); // start sending bytes
- ok &= waitForGD0High();
- ok &= waitForGD0Low();
- ok &= strobe(CC1101_SFTX); //flush TXfifo
- return ok;
-}
-
-bool Cc1101::setReceive () {
- return strobe(CC1101_SRX);
-}
-
-// byte CheckReceiveFlag(void)
-// if(digitalRead(GDO0)) //receive data
-// {
-// while (digitalRead(GDO0));
-// return 1;
-// }
-// else // no data
-// {
-// return 0;
-// }
-// }
-
-bool Cc1101::receiveData (uint8_t *buffer, uint8_t *receivedLength, uint8_t maxBufferSize) {
- bool ok = true;
- uint8_t status[2];
- uint8_t length;
-
- ok &= readStatus(CC1101_RXBYTES, status);
- if (ok && status[0] & BYTES_IN_RXFIFO) {
- ok &= readRegister(CC1101_RXFIFO, &length);
- if (ok && length > 0 && length <= maxBufferSize) {
- ok &= readRegisters(CC1101_RXFIFO, buffer, length);
- ok &= readRegisters(CC1101_RXFIFO, status, 2);
- ok &= strobe(CC1101_SFRX);
- if (ok) {
- *receivedLength = length;
- return ok;
- }
- }
- }
- strobe(CC1101_SFRX);
- *receivedLength = 0;
- return false;
-}
-
-bool Cc1101::initModem () {
- bool ok = true;
- SPCR = 0;
-
- setChipEnableLow();
- _delay_us(20);
- setChipEnableHigh();
- _delay_us(30);
- setChipEnableLow();
- timer = 10;
- ok &= waitForMisoLow();
- SPCR = (1 << SPE) | (1 << MSTR); // SPI enable , Master, f=12MHz/4 = 3MHz
- SPDR = CC1101_SRES;
- while (!(SPSR & (1<<SPIF))) {}
- ok &= waitForMisoLow();
- setChipEnableHigh();
-
- PORTB |= (1 << PB0);
-
- ok &= initModemConfig(MHZ868);
- uint8_t pa_table[8];
- memcpy_P(pa_table, PMEM_CC1101_PA_TABLE, 8);
- ok &= writeRegisters(CC1101_PATABLE, pa_table, 8);
-
- PORTB &= ~(1 << PB0);
- return ok;
-}
-
-
-bool Cc1101::initModemConfig (InitFrequency f) {
- bool ok = true;
-
- ok &= writeRegister(CC1101_FSCTRL1, 0x08); // frequency synthesizer control 1 (RX frequency)
- ok &= writeRegister(CC1101_FSCTRL1, 0x08); // frequency synthesizer control 1 (RX frequency)
- ok &= writeRegister(CC1101_FSCTRL0, 0x00); // frequency synthesizer control 0 (RX frequency offset)
-
- switch (f) {
- case MHZ868:
- ok &= writeRegister(CC1101_FREQ2, F2_868); // frequency high byte
- ok &= writeRegister(CC1101_FREQ1, F1_868); // frequency middle byte
- ok &= writeRegister(CC1101_FREQ0, F0_868); // frequency low byte
- break;
-
- case MHZ915:
- ok &= writeRegister(CC1101_FREQ2, F2_915); // frequency high byte
- ok &= writeRegister(CC1101_FREQ1, F1_915); // frequency middle byte
- ok &= writeRegister(CC1101_FREQ0, F0_915); // frequency low byte
- break;
-
- // case MHZ433: // not supported by E07-900MM1DS
- // ok &= writeRegister(CC1101_FREQ2, F2_433);
- // ok &= writeRegister(CC1101_FREQ1, F1_433);
- // ok &= writeRegister(CC1101_FREQ0, F0_433);
- // break;
-
- default: return false;
- }
-
- for (uint8_t i = 0; i < sizeof(PMEM_CC1101_INIT); i += 2) {
- uint16_t w = pgm_read_word(PMEM_CC1101_INIT + i);
- ok &= writeRegister(w & 0xff, w >> 8);
- }
-
- return ok;
-}
-
-int8_t Cc1101::run (uint8_t subtest) {
- if (subtest == 0) {
- printf_P(PSTR("\n => init CC1101 ... "));
- if (!initModem()) {
- printf_P(PSTR("E1"));
- return -1;
- }
- printf_P(PSTR("done, read Version ... "));
- uint8_t status;
- if (readStatus(CC1101_VERSION, &status)) {
- printf_P(PSTR("0x%02x"), status);
- if (status == 0x14) {
- printf_P(PSTR(" -> OK (CC1101 detected)"));
- } else {
- printf_P(PSTR("E2"));
- }
- } else {
- printf_P(PSTR("E3"));
- }
- return 0;
-
- } else if (subtest == 1) {
- uint8_t value;
- for (uint8_t addr = 0; addr <= 0x3d; addr++) {
- printf_P(PSTR("\n reg 0x%02x: "), addr);
- if (readRegister(addr, &value)) {
- printf_P(PSTR("0x%02x: "), value);
- } else {
- printf_P(PSTR("?"));
- }
- }
-
- return 0;
-
- } else if (subtest == 2) {
- do {
- uint8_t status;
- printf_P(PSTR("\n => status: "));
- triggerOn();
- if (readStatus(CC1101_MARCSTATE, &status)) {
- printf_P(PSTR("0x%02x"), status);
- } else {
- printf_P(PSTR("E4"));
- }
- triggerOff();
- } while (wait(2000) == EOF);
- }
-
- return -1;
-}
-
--- /dev/null
+#include <stdio.h>
+#include <avr/io.h>
+#include <avr/pgmspace.h>
+#include <util/delay.h>
+
+#include "cc1101.hpp"
+#include "../main.hpp"
+
+// 868MHz Modem E07-900MM1DS (chipset CC1101)
+// https://jlcpcb.com/partdetail/Chengdu_Ebyte_ElecTech-E07900MM10S/C5844212
+
+#ifdef __AVR_ATmega328P__
+
+ // Arduino-Nano-5V
+ // ------------------------------------
+ // not available
+
+ void PortExp::init () {}
+ void PortExp::cleanup () {}
+ void PortExp::setChipEnable () {}
+ void PortExp::clearChipEnable () {}
+
+#endif
+
+
+#ifdef __AVR_ATmega644P__
+
+ // Nano-644
+ // --------------------------------------------------------
+ // PA4 ... nCS
+ // PB5 ... MOSI
+ // PB6 ... MISO
+ // PB7 ... SCK
+
+const uint8_t PMEM_CC1101_INIT[] PROGMEM = {
+ CC1101_MDMCFG4, 0x5B, // modem config 4 -> ADC decimation rate, symbol rate exponent
+ CC1101_MDMCFG3, 0xF8, // modem config 3 -> symbol rate mantissa
+ CC1101_MDMCFG2, 0x03, // modem config 2 -> DC blocking filter, modulation type, manchaster enoding, sync-mode,
+ CC1101_MDMCFG1, 0x22, // modem config 1 -> forw error correction, min number of preamble bytes, channel spacing exponent
+ CC1101_MDMCFG0, 0xF8, // modem config 0 -> channel spacing mantissa
+ CC1101_CHANNR, 0x00, // channel number
+ CC1101_DEVIATN, 0x47, // modem deviation setting
+ CC1101_FREND1, 0xB6, // front end RX configuration
+ CC1101_FREND0, 0x10, // front end TX configuration
+ CC1101_MCSM0 , 0x18, // Main Radio Control State Machine Configuration
+ CC1101_FOCCFG, 0x1D, // Frequency Offset Compensation Configuration
+ CC1101_BSCFG, 0x1C, // Bit Synchronization Configuration
+ CC1101_AGCCTRL2, 0xC7, // AGC Control
+ CC1101_AGCCTRL1, 0x00, // AGC Control
+ CC1101_AGCCTRL0, 0xB2, // AGC Control
+ CC1101_FSCAL3, 0xEA, // Frequency Synthesizer Calibration
+ CC1101_FSCAL2, 0x2A, // Frequency Synthesizer Calibration
+ CC1101_FSCAL1, 0x00, // Frequency Synthesizer Calibration
+ CC1101_FSCAL0, 0x11, // Frequency Synthesizer Calibration
+ // CC1101_FSTEST, 0x59, // Frequency Synthesizer Calibration Control
+ // CC1101_TEST2, 0x81, // Various Test Settings
+ // CC1101_TEST1, 0x35, // Various Test Settings
+ // CC1101_TEST0, 0x09, // Various Test Settings
+ CC1101_IOCFG2, 0x0B, // GDO2 Output Pin Configuration -> Serial Clock. Synchronous to the data in synchronous serial mode.
+ CC1101_IOCFG0, 0x06, // GDO0 Output Pin Configuration -> Asserts when sync word has been sent / received, and de-asserts at the end of the packet.
+ CC1101_PKTCTRL1, 0x04, // Packet Automation Control
+ CC1101_PKTCTRL0, 0x05, // serial clock.synchronous to the data in synchronous serial mode
+ CC1101_ADDR, 0x00, // asserts when sync word has been sent/received, and de-asserts at the end of the packet
+ CC1101_PKTLEN, 0x3D, // two status bytes will be appended to the payload of the packet,including RSSI LQI and CRC OK
+ CC1101_PKTCTRL0, 0x05, // whitening off; normal mode, CRC enabled, variable packet length
+ CC1101_ADDR, 0x00, // address used for packet filtration.
+ CC1101_PKTLEN, 0x3D // 61 bytes max length
+};
+
+
+const uint8_t PMEM_CC1101_PA_TABLE[8] PROGMEM = { 0x60 ,0x60 ,0x60 ,0x60 ,0x60 ,0x60 ,0x60 ,0x60 };
+
+ void Cc1101::triggerOn () {
+ PORTB |= (1 << PB0);
+ }
+
+ void Cc1101::triggerOff () {
+ PORTB &= ~(1 << PB0);
+ }
+
+ void Cc1101::init () {
+ // trigger for debugging
+ PORTB &= ~(1 << PB0);
+ DDRB |= ( 1 << PB0);
+
+ PRR &= (1 << PRSPI);
+ PORTA |= (1 << PA4);
+ DDRA |= (1 << PA4); // SPI nCS
+ // PORTB/DDRB must be configured before SPCR !!
+ PORTB |= (1 << PB4); // nSS must be HIGH, otherwise SPI master will not become active!!
+ DDRB &= ~(1 << PB6); // MISO
+ DDRB |= (1 << PB7) | (1 << PB5) | (1 << PB4); // SPI SCK (=PB7) and SPI MOSI (=PB5)
+
+ // SPCR |= (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); // SPI enable , Master, f=12MHz/128=93,75kHz
+ SPCR = (1 << SPE) | (1 << MSTR); // SPI enable , Master, f=12MHz/4 = 3MHz
+
+ // GDO0
+ PORTA |= (1 << PA5);
+ DDRA &= ~(1 << PA5);
+ }
+
+ void Cc1101::cleanup () {
+ // trigger for debugging
+ PORTB &= ~(1 << PB0);
+ DDRB &= ~( 1 << PB0);
+
+ SPCR = 0;
+ DDRB &= ~((1 << PB7) | (1 << PB6) | (1 << PB5) | (1 << PB4));
+ DDRA &= ~((1 << PA5) | (1 << PA4));
+ PORTA &= ~((1 << PA5) | (1 << PA4));
+ }
+
+
+
+
+ void Cc1101::setChipEnableLow () {
+ PORTA &= ~(1 << PA4);
+ }
+
+ void Cc1101::setChipEnableHigh () {
+ PORTA |= (1 << PA4);
+ }
+
+ bool Cc1101::isMisoHigh () {
+ return (PINB & (1 << PB6)) != 0;
+ }
+
+ bool Cc1101::isGd0High () {
+ return (PINA & (1 << PA5)) != 0;
+ }
+
+#endif
+
+uint8_t Cc1101::sendSpiByte (uint8_t b) {
+ SPDR = b;
+ while (!(SPSR & (1<<SPIF))) {}
+ return SPDR;
+}
+
+bool Cc1101::waitForMisoLow () {
+ timer = 10;
+ while (isMisoHigh()) {
+ if (timer == 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool Cc1101::waitForGD0High () {
+ timer = 100;
+ while (!isGd0High()) {
+ if (timer == 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool Cc1101::waitForGD0Low () {
+ timer = 100;
+ while (isGd0High()) {
+ if (timer == 0) {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+
+bool Cc1101::writeRegister (uint8_t addr, uint8_t value) {
+ bool ok = true;
+ timer = 10;
+ setChipEnableLow();
+ ok &= waitForMisoLow();
+ sendSpiByte(addr);
+ sendSpiByte(value);
+ setChipEnableHigh();
+ return ok;
+}
+
+bool Cc1101::writeRegisters (uint8_t addr, uint8_t *buffer, uint8_t length) {
+ bool ok = true;
+
+ addr |= WRITE_BURST;
+ setChipEnableLow();
+ ok &= waitForMisoLow();
+ sendSpiByte(addr);
+ while (length-- > 0) {
+ sendSpiByte(*buffer++);
+ }
+ setChipEnableHigh();
+ return ok;
+}
+
+bool Cc1101::strobe (uint8_t strobe) {
+ bool ok = true;
+ setChipEnableLow();
+ ok &= waitForMisoLow();
+ sendSpiByte(strobe);
+ setChipEnableHigh();
+ return ok;
+}
+
+
+bool Cc1101::readRegister (uint8_t addr, uint8_t *value) {
+ bool ok = true;
+
+ addr |= READ_SINGLE;
+ setChipEnableLow();
+ ok &= waitForMisoLow();
+ sendSpiByte(addr);
+ *value = sendSpiByte(0);
+ setChipEnableHigh();
+ return ok;
+}
+
+bool Cc1101::readRegisters (uint8_t addr, uint8_t *buffer, uint8_t length) {
+ bool ok = true;
+
+ addr |= READ_BURST;
+ setChipEnableLow();
+ ok &= waitForMisoLow();
+ sendSpiByte(addr);
+ while (length-- > 0) {
+ *buffer++ = sendSpiByte(0);
+ }
+ setChipEnableHigh();
+ return ok;
+}
+
+bool Cc1101::readStatus (uint8_t addr, uint8_t *status) {
+ return readRegisters(addr, status, 1);
+ // bool ok = true;
+
+ // addr |= READ_BURST;
+ // setChipEnableLow();
+ // ok &= waitForMisoLow();
+ // sendSpiByte(addr);
+ // *status = sendSpiByte(0);
+ // setChipEnableHigh();
+ // return ok;
+}
+
+bool Cc1101::sendData (uint8_t *buffer, uint8_t length) {
+ bool ok = true;
+ ok &= writeRegister(CC1101_TXFIFO, length);
+ ok &= writeRegisters(CC1101_TXFIFO, buffer, length);
+ ok &= strobe(CC1101_STX); // start sending bytes
+ ok &= waitForGD0High();
+ ok &= waitForGD0Low();
+ ok &= strobe(CC1101_SFTX); //flush TXfifo
+ return ok;
+}
+
+bool Cc1101::setReceive () {
+ return strobe(CC1101_SRX);
+}
+
+// byte CheckReceiveFlag(void)
+// if(digitalRead(GDO0)) //receive data
+// {
+// while (digitalRead(GDO0));
+// return 1;
+// }
+// else // no data
+// {
+// return 0;
+// }
+// }
+
+bool Cc1101::receiveData (uint8_t *buffer, uint8_t *receivedLength, uint8_t maxBufferSize) {
+ bool ok = true;
+ uint8_t status[2];
+ uint8_t length;
+
+ ok &= readStatus(CC1101_RXBYTES, status);
+// printf(" 1-%d", ok);
+ if (ok && status[0] & BYTES_IN_RXFIFO) {
+// printf(" 2-%d", ok);
+ ok &= readRegister(CC1101_RXFIFO, &length);
+// printf(" 3-%d", ok);
+ if (ok && length > 0 && length <= maxBufferSize) {
+// printf(" 4-%d", ok);
+ ok &= readRegisters(CC1101_RXFIFO, buffer, length);
+// printf(" 5-%d", ok);
+ ok &= readRegisters(CC1101_RXFIFO, status, 2);
+// printf(" 6-%d", ok);
+ ok &= strobe(CC1101_SFRX);
+// printf(" 7-%d", ok);
+ if (ok) {
+ *receivedLength = length;
+ return ok;
+ }
+ }
+ }
+// printf(" 8-%d", ok);
+ strobe(CC1101_SFRX);
+ *receivedLength = 0;
+ return false;
+}
+
+bool Cc1101::initModem () {
+ bool ok = true;
+ SPCR = 0;
+
+ setChipEnableLow();
+ _delay_us(20);
+ setChipEnableHigh();
+ _delay_us(30);
+ setChipEnableLow();
+ timer = 10;
+ ok &= waitForMisoLow();
+ SPCR = (1 << SPE) | (1 << MSTR); // SPI enable , Master, f=12MHz/4 = 3MHz
+ SPDR = CC1101_SRES;
+ while (!(SPSR & (1<<SPIF))) {}
+ ok &= waitForMisoLow();
+ setChipEnableHigh();
+
+ PORTB |= (1 << PB0);
+
+ ok &= initModemConfig(MHZ868);
+ uint8_t pa_table[8];
+ memcpy_P(pa_table, PMEM_CC1101_PA_TABLE, 8);
+ ok &= writeRegisters(CC1101_PATABLE, pa_table, 8);
+
+ PORTB &= ~(1 << PB0);
+ return ok;
+}
+
+
+bool Cc1101::initModemConfig (InitFrequency f) {
+ bool ok = true;
+
+ ok &= writeRegister(CC1101_FSCTRL1, 0x08); // frequency synthesizer control 1 (RX frequency)
+ ok &= writeRegister(CC1101_FSCTRL1, 0x08); // frequency synthesizer control 1 (RX frequency)
+ ok &= writeRegister(CC1101_FSCTRL0, 0x00); // frequency synthesizer control 0 (RX frequency offset)
+
+ switch (f) {
+ case MHZ868:
+ ok &= writeRegister(CC1101_FREQ2, F2_868); // frequency high byte
+ ok &= writeRegister(CC1101_FREQ1, F1_868); // frequency middle byte
+ ok &= writeRegister(CC1101_FREQ0, F0_868); // frequency low byte
+ break;
+
+ case MHZ915:
+ ok &= writeRegister(CC1101_FREQ2, F2_915); // frequency high byte
+ ok &= writeRegister(CC1101_FREQ1, F1_915); // frequency middle byte
+ ok &= writeRegister(CC1101_FREQ0, F0_915); // frequency low byte
+ break;
+
+ // case MHZ433: // not supported by E07-900MM1DS
+ // ok &= writeRegister(CC1101_FREQ2, F2_433);
+ // ok &= writeRegister(CC1101_FREQ1, F1_433);
+ // ok &= writeRegister(CC1101_FREQ0, F0_433);
+ // break;
+
+ default: return false;
+ }
+
+ for (uint8_t i = 0; i < sizeof(PMEM_CC1101_INIT); i += 2) {
+ uint16_t w = pgm_read_word(PMEM_CC1101_INIT + i);
+ ok &= writeRegister(w & 0xff, w >> 8);
+ }
+
+ return ok;
+}
+
+int8_t Cc1101::run (uint8_t subtest) {
+ if (subtest == 0) {
+ printf_P(PSTR("\n => init CC1101 ... "));
+ if (!initModem()) {
+ printf_P(PSTR("E1"));
+ return -1;
+ }
+ printf_P(PSTR("done, read Version ... "));
+ uint8_t status;
+ if (readStatus(CC1101_VERSION, &status)) {
+ printf_P(PSTR("0x%02x"), status);
+ if (status == 0x14) {
+ printf_P(PSTR(" -> OK (CC1101 detected)"));
+ } else {
+ printf_P(PSTR("E2"));
+ }
+ } else {
+ printf_P(PSTR("E3"));
+ }
+ return 0;
+
+ } else if (subtest == 1) {
+ uint8_t value;
+ for (uint8_t addr = 0; addr <= 0x3d; addr++) {
+ printf_P(PSTR("\n reg 0x%02x: "), addr);
+ if (readRegister(addr, &value)) {
+ printf_P(PSTR("0x%02x: "), value);
+ } else {
+ printf_P(PSTR("?"));
+ }
+ }
+
+ return 0;
+
+ } else if (subtest == 2) {
+ do {
+ uint8_t data[16];
+ for (uint8_t i = 0; i < sizeof(data); i++) {
+ data[i] = i;
+ }
+ printf_P(PSTR("\n => send 16 bytes ..."));
+ triggerOn();
+ if (sendData(data, sizeof(data))) {
+ flashGreenLed(100);
+ printf_P(PSTR("OK"));
+ } else {
+ flashRedLed(100);
+ printf_P(PSTR("E4"));
+ }
+ triggerOff();
+
+ } while (wait(2000) == EOF);
+ return 0;
+
+ } else if (subtest == 3) {
+ setReceive();
+ int key = EOF;
+ uint8_t state;
+ while (key == EOF) {
+ printf_P(PSTR("\n => receive: "));
+ if (!readStatus(CC1101_MARCSTATE, &state)) {
+ flashRedLed(100);
+ _delay_ms(500);
+ continue;
+ }
+ if (state == 0x01) {
+ uint8_t states[8] = { 0x01 };
+ uint8_t statesIndex = 1;
+ printf_P(PSTR("start "));
+ setReceive();
+ for (uint16_t i = 0; i < 1000; i++) {
+ uint8_t s;
+ if (!readStatus(CC1101_MARCSTATE, &s)) {
+ continue;
+ }
+ if (statesIndex == 0 || (states[statesIndex - 1] != s && statesIndex < sizeof(states))) {
+ states[statesIndex++] = s;
+ }
+ if (s == 0x13) {
+ break;
+ }
+ }
+ printf_P(PSTR(" State:"));
+ for (uint8_t i = 0; i < statesIndex; i++) {
+ printf_P(PSTR(" 0x%02x"), states[i]);
+ }
+ }
+
+ key = wait(0);
+
+ while (key == EOF && state != 0x01) {
+ uint8_t length;
+ uint8_t data[16];
+ printf_P(PSTR(" -> receive ... "));
+
+ while (key == EOF) {
+ if (receiveData(data, &length, sizeof(data))) {
+ flashGreenLed(100);
+ printf_P(PSTR("OK, %d bytes received: "), length);
+ for (uint8_t i = 0; i < length; i++) {
+ printf_P(PSTR(" 0x%02x"), data[i]);
+ }
+ break;
+ } else {
+ state = 0;
+ if (!readStatus(CC1101_MARCSTATE, &state) || state == 0x01 || state == 0x13) {
+ printf_P(PSTR(" -> cancelled state=0x%02x"), state);
+ break;
+ }
+ if (state != 0x0d) {
+ printf_P(PSTR(" -> state=0x%02x "), state);
+ }
+ }
+ key = wait(0);
+ }
+ }
+ }
+ return 0;
+
+ } else if (subtest == 4) {
+ return 0;
+
+ } else if (subtest == 5) {
+ do {
+ uint8_t status;
+ printf_P(PSTR("\n => status: "));
+ if (readStatus(CC1101_MARCSTATE, &status)) {
+ printf_P(PSTR("0x%02x"), status);
+ } else {
+ printf_P(PSTR("E6"));
+ }
+ } while (wait(2000) == EOF);
+ }
+
+ return -1;
+}
+
private:
+ enum MainRadioControlState {
+ SLEEP = 0,
+ IDLE = 1,
+ XOFF = 2,
+ MANCAL_VCOON = 3,
+ MANCAL_REGON = 4,
+ MANCAL = 5,
+ FS_WAKEUP_VCOON = 6,
+ FS_WAKEUP_REGON = 7,
+ CALIBRATE_START = 8,
+ SETTLING_BWBOOST = 9,
+ SETTLING_FS_LOCK = 10,
+ SETTLIN_IFADCON = 11,
+ CALIBRATE_END = 12,
+ RX = 13,
+ RX_END = 14,
+ RX_RST = 15,
+ TXRX_SETTLING = 16,
+ RXFIFO_OVERFLOW = 17,
+ FXTXON = 18,
+ TX = 19,
+ TX_END = 20,
+ RXTX_SETTLING = 21,
+ TXFIFO_UNDERFLOW = 22
+ };
+
#define WRITE_BURST 0x40
#define READ_SINGLE 0x80