Commit c9dd1076d366323e4fdbdcbcf6cc92c05af90f51
receivedSat, 10. Aug 2024, 10:13:27 (by user sx)
Sat, 10 Aug 2024 08:13:27 +0000 (10:13 +0200)
authorManfred Steiner <sx@htl-kaindorf.at>
Sat, 10 Aug 2024 08:13:21 +0000 (10:13 +0200)
committerManfred Steiner <sx@htl-kaindorf.at>
Sat, 10 Aug 2024 08:13:21 +0000 (10:13 +0200)
6 files changed:
software/nano-644/test_2024-07-23/Makefile
software/nano-644/test_2024-07-23/src/main.cpp
software/nano-644/test_2024-07-23/src/main.hpp
software/nano-644/test_2024-07-23/src/units/cc1011.cpp [deleted file]
software/nano-644/test_2024-07-23/src/units/cc1101.cpp [new file with mode: 0644]
software/nano-644/test_2024-07-23/src/units/cc1101.hpp

index be31a04715928a7ebf0768668730388b9a903169..4cdd4556e24be77c519ea216cfd094b8a11b3dfa 100644 (file)
@@ -4,8 +4,9 @@ $(shell mkdir -p build >/dev/null)
 $(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)
@@ -24,19 +25,28 @@ LFLAGS_SIM= -Wall -mmcu=$(DEVICE) -Og -DF_CPU=12000000 -g -Wl,-u,vfprintf -lprin
 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)
index 78fe57b9d910e579d3641e139493bf86894bb0a6..94a404ff24679182ec6c1d1a029be396cca4644f 100644 (file)
@@ -77,6 +77,33 @@ extern "C" {
    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;
 
@@ -273,6 +300,18 @@ ISR (TIMER2_COMPA_vect) { // every 100us
       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++;
index bef51b6ffc1712c8b8c60dcfa61ebff6f922fe75..e5bf840f8f7e2856f222065ac4cbb9eb89dad664 100644 (file)
 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;
diff --git a/software/nano-644/test_2024-07-23/src/units/cc1011.cpp b/software/nano-644/test_2024-07-23/src/units/cc1011.cpp
deleted file mode 100644 (file)
index 962043d..0000000
+++ /dev/null
@@ -1,406 +0,0 @@
-#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;
-}
-
diff --git a/software/nano-644/test_2024-07-23/src/units/cc1101.cpp b/software/nano-644/test_2024-07-23/src/units/cc1101.cpp
new file mode 100644 (file)
index 0000000..6b6809b
--- /dev/null
@@ -0,0 +1,506 @@
+#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;
+}
+
index 64dd5787d2db78c82e31613abcda05f832a29929..b36231490e1d2114b159f339a175145079331a3f 100644 (file)
@@ -51,6 +51,32 @@ class Cc1101 : public TestUnit {
       
    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