From e44f0b671e103669bc3cc1d395a5b16b4e42051b Mon Sep 17 00:00:00 2001 From: habeIchVergessen Date: Sat, 15 Jul 2017 10:37:49 +0200 Subject: [PATCH 01/40] cc1101 detection added copy & paste from [SIGNALDuino cc1101](https://github.com/RFD-FHEM/SIGNALDuino/tree/dev-r33_cc1101) --- SIGNALESP/SIGNALESP.ino | 279 ++++++++++++++------- SIGNALESP/cc1101.h | 522 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 716 insertions(+), 85 deletions(-) create mode 100644 SIGNALESP/cc1101.h diff --git a/SIGNALESP/SIGNALESP.ino b/SIGNALESP/SIGNALESP.ino index ea44ba6..0ed0e4d 100644 --- a/SIGNALESP/SIGNALESP.ino +++ b/SIGNALESP/SIGNALESP.ino @@ -5,16 +5,18 @@ #define VERSION_1 0x33 #define VERSION_2 0x1d +#define CMP_CC1101 #define PIN_RECEIVE 2 #define PIN_LED 16 #define PIN_SEND 0 #define BAUDRATE 115200 -#define FIFO_LENGTH 200 -#define DEBUG 1 +#define FIFO_LENGTH 200 +#define DEBUG 1 #define ETHERNET_PRINT +#include #include #include //Local DNS Server used for redirecting all requests to the configuration portal #include //Local WebServer used to serve the configuration portal @@ -32,16 +34,15 @@ SimpleFIFO FiFo; //store FIFO_LENGTH # ints SignalDetectorClass musterDec; -#include - +#ifdef CMP_CC1101 + #include "cc1101.h" +#endif #define pulseMin 90 volatile bool blinkLED = false; String cmdstring = ""; volatile unsigned long lastTime = micros(); - - #define digitalLow(P) digitalWrite(P,LOW) #define digitalHigh(P) digitalWrite(P,HIGH) #define isHigh(P) (digitalRead(P) == HIGH) @@ -52,21 +53,19 @@ extern "C" { #include "user_interface.h" } - os_timer_t cronTimer; - +bool hasCC1101 = false; // EEProm Addresscommands -#define addr_init 0 -#define addr_features 1 #define EE_MAGIC_OFFSET 0 +#define addr_features EE_MAGIC_OFFSET+2 #define MAX_SRV_CLIENTS 2 -//void handleInterrupt(); +void handleInterrupt(); void enableReceive(); void disableReceive(); void serialEvent(); @@ -82,6 +81,7 @@ void getPing(); void configCMD(); void storeFunctions(const int8_t ms = 1, int8_t mu = 1, int8_t mc = 1); void getFunctions(bool *ms, bool *mu, bool *mc); +uint8_t rssiCallback() { return 0; }; // Dummy return if no rssi value can be retrieved from receiver @@ -109,13 +109,36 @@ bool startWPS() { void setup() { //ESP.wdtEnable(2000); + Serial.begin(115200); + while (!Serial) - { - delay(90); - } + delay(90); + + Serial.println("\n\n"); + + pinMode(PIN_RECEIVE, INPUT); + pinMode(PIN_LED, OUTPUT); + +#ifdef CMP_CC1101 + cc1101::setup(); +#endif + + initEEPROM(); + +#ifdef CMP_CC1101 + cc1101::CCinit(); + hasCC1101 = cc1101::checkCC1101(); + + if (hasCC1101) { + DBG_PRINTLN("CC1101 found"); +// musterDec.setRSSICallback(&cc1101::getRSSI); // Provide the RSSI Callback + }// else +// musterDec.setRSSICallback(&rssiCallback); // Provide the RSSI Callback +#endif + #ifdef DEBUG - Serial.printf("\nTry connecting to WiFi with SSID '%s'\n", WiFi.SSID().c_str()); + Serial.printf("\nTry connecting to WiFi with SSID '%s'\n", WiFi.SSID().c_str()); #endif WiFi.mode(WIFI_STA); WiFi.begin(WiFi.SSID().c_str(), WiFi.psk().c_str()); // reading data from EPROM, @@ -154,8 +177,6 @@ void setup() { #endif } - - WiFiManager wifiManager; wifiManager.setBreakAfterConfig(true); //reset settings - for testing @@ -179,29 +200,6 @@ void setup() { Serial.println("local ip"); Serial.println(WiFi.localIP()); - - - //pinMode(PIN_RECEIVE, INPUT); - //pinMode(PIN_SEND, OUTPUT); - //pinMode(PIN_LED, OUTPUT); - - initEEPROM(); - //musterDec.MSenabled = musterDec.MUenabled = musterDec.MCenabled = true; - /* - if (EEPROM.read(addr_init) == 0xB) - { - #ifdef DEBUG - Serial.println("Reading values fom eeprom"); - #endif - getFunctions(&musterDec.MSenabled, &musterDec.MUenabled, &musterDec.MCenabled); - } - else { - EEPROM.write(addr_init, 0xB); - storeFunctions(1, 1, 1); // Init EEPROM with all flags enabled - #ifdef DEBUG - Serial.println("Init eeprom to defaults after flash"); - #endif - }*/ Server.begin(); // telnet server Server.setNoDelay(true); @@ -209,7 +207,13 @@ void setup() { os_timer_setfn(&cronTimer, cronjob, NULL); os_timer_arm(&cronTimer, 31, true); - enableReceive(); + if (!hasCC1101 || cc1101::regCheck()) { + enableReceive(); + DBG_PRINTLN(F("receiver enabled")); + } else { + DBG_PRINTLN(F("cc1101 is not correctly set. Please do a factory reset via command e")); + } + cmdstring.reserve(40); } @@ -244,6 +248,27 @@ void loop() { if (state) blinkLED = true; //LED blinken, wenn Meldung dekodiert yield(); } + + if (Serial.available()) { + int16_t sDuration = 620; + + switch(Serial.read()) { + case 'b': + FiFo.enqueue(sDuration); + for (uint8_t i=0; i<55; i++) { + FiFo.enqueue(-sDuration*2); + FiFo.enqueue(sDuration); + } + FiFo.enqueue(-sDuration); + break; + case 'c': + Serial.println("currentMode: 0x" + String(cc1101::currentMode(), HEX)); + break; + case 'd': + dumpEEPROM(); + break; + } + } } @@ -267,25 +292,35 @@ void ICACHE_RAM_ATTR handleInterrupt() { } FiFo.enqueue(sDuration); } // else => trash - } void enableReceive() { - attachInterrupt(PIN_RECEIVE, handleInterrupt, CHANGE); + attachInterrupt(PIN_RECEIVE, handleInterrupt, CHANGE); + + #ifdef CMP_CC1101 + if (hasCC1101) + cc1101::setReceiveMode(); + Serial.println("receiver enabled!"); + #endif } void disableReceive() { - detachInterrupt(PIN_RECEIVE); + detachInterrupt(PIN_RECEIVE); + + #ifdef CMP_CC1101 + if (hasCC1101) + cc1101::setIdleMode(); + Serial.println("receiver disabled!"); + #endif } - - - //============================== IT_Send ========================================= //================================= RAW Send ====================================== void send_raw(const uint8_t startpos, const uint16_t endpos, const int16_t *buckets, String *source = &cmdstring) { + pinMode(PIN_SEND, OUTPUT); + uint8_t index = 0; unsigned long stoptime = micros(); bool isLow; @@ -313,11 +348,10 @@ void send_raw(const uint8_t startpos, const uint16_t endpos, const int16_t *buck } //SM;R=2;C=400;D=AFAFAF; - - - void send_mc(const uint8_t startpos, const uint8_t endpos, const int16_t clock) { + pinMode(PIN_SEND, OUTPUT); + int8_t b; char c; //digitalHigh(PIN_SEND); @@ -376,6 +410,8 @@ struct s_sendcmd { void send_cmd() { + pinMode(PIN_SEND, OUTPUT); + #define combined 0 #define manchester 1 #define raw 2 @@ -458,6 +494,11 @@ void send_cmd() } } +#ifdef CMP_CC1101 + if (hasCC1101) + cc1101::setTransmitMode(); +#endif + for (uint8_t i = 0; i read EEPROM + reg = cmdstringPos2int(1); + MSG_PRINT(F("EEPROM ")); + printHex2(reg); + if (cmdstring.charAt(3) == 'n') { + MSG_PRINT(F(" :")); + for (uint8_t i = 0; i < 16; i++) { + MSG_PRINT(" "); + printHex2(EEPROM.read(reg + i)); + } + } else { + MSG_PRINT(F(" = ")); + printHex2(EEPROM.read(reg)); + } + MSG_PRINTLN(""); + } else if (cmdstring.charAt(0) == cmd_patable && isHexadecimalDigit(cmdstring.charAt(1)) && isHexadecimalDigit(cmdstring.charAt(2)) && hasCC1101) { + val = cmdstringPos2int(1); + cc1101::writeCCpatable(val); + MSG_PRINT(F("Write ")); + printHex2(val); + MSG_PRINTLN(F(" to PATABLE done")); + EEPROM.commit(); + } else if (cmdstring.charAt(0) == cmd_ccFactoryReset && hasCC1101) { + cc1101::ccFactoryReset(); + cc1101::CCinit(); + EEPROM.commit(); + } else if (cmdstring.charAt(0) == cmd_write) { // write EEPROM und CC11001 register + if (cmdstring.charAt(1) == 'S' && cmdstring.charAt(2) == '3' && hasCC1101) { // WS Command Strobes + cc1101::commandStrobes(); + } else if (isHexadecimalDigit(cmdstring.charAt(1)) && isHexadecimalDigit(cmdstring.charAt(2)) && isHexadecimalDigit(cmdstring.charAt(3)) && isHexadecimalDigit(cmdstring.charAt(4))) { + reg = cmdstringPos2int(1); + val = cmdstringPos2int(3); + if (hasCC1101) { + cc1101::writeCCreg(reg, val); + EEPROM.commit(); + } + } +#endif } else { - MSG_PRINTLN(F("Unsupported command")); + MSG_PRINT(F("Unsupported command")); + MSG_PRINTLN(" -> 0x" + String(cmdstring.charAt(0), HEX) + " " + cmdstring); } } @@ -616,8 +707,12 @@ void configCMD() } else if (cmdstring.charAt(1) == 'D') { // Disable *bptr = false; - } - else { +#ifdef CMP_CC1101 + } else if (isHexadecimalDigit(cmdstring.charAt(1)) && isHexadecimalDigit(cmdstring.charAt(2)) && hasCC1101) { + uint8_t reg = cmdstringPos2int(1); + cc1101::readCCreg(reg); +#endif + } else { return; } storeFunctions(musterDec.MSenabled, musterDec.MUenabled, musterDec.MCenabled); @@ -715,54 +810,68 @@ void storeFunctions(const int8_t ms, int8_t mu, int8_t mc) { mu = mu << 1; mc = mc << 2; - EEPROM.begin(512); //Max bytes of eeprom to use - yield(); - - int8_t dat = ms | mu | mc; EEPROM.write(addr_features, dat); - EEPROM.commit(); - EEPROM.end(); } void getFunctions(bool *ms, bool *mu, bool *mc) { - EEPROM.begin(512); //Max bytes of eeprom to use - yield(); int8_t dat = EEPROM.read(addr_features); - EEPROM.end(); - *ms = bool(dat &(1 << 0)); *mu = bool(dat &(1 << 1)); *mc = bool(dat &(1 << 2)); - - } +void dumpEEPROM() { + Serial.println("\ndump EEPROM:"); + for (uint8_t i=0; i<56; i++) { + String temp=String(EEPROM.read(i), HEX); + Serial.print((temp.length() == 1 ? "0" : "") + temp + " "); + if ((i & 0x0F) == 0x0F) + Serial.println(""); + } + Serial.println(""); +} -void initEEPROM(void) { +void initEEPROM() { EEPROM.begin(512); //Max bytes of eeprom to use - yield(); + if (EEPROM.read(EE_MAGIC_OFFSET) == VERSION_1 && EEPROM.read(EE_MAGIC_OFFSET + 1) == VERSION_2) { DBG_PRINTLN("Reading values fom eeprom"); - } - else { - storeFunctions(1, 1, 1); // Init EEPROM with all flags enabled + } else { + DBG_PRINTLN("Init eeprom to defaults after flash"); + EEPROM.write(EE_MAGIC_OFFSET, VERSION_1); + EEPROM.write(EE_MAGIC_OFFSET + 1, VERSION_2); storeFunctions(1, 1, 1); // Init EEPROM with all flags enabled //hier fehlt evtl ein getFunctions() - DBG_PRINTLN("Init eeprom to defaults after flash"); - EEPROM.write(EE_MAGIC_OFFSET, VERSION_1); - EEPROM.write(EE_MAGIC_OFFSET + 1, VERSION_2); - // if (hasCC1101) { // der ccFactoryReset muss auch durchgefuehrt werden, wenn der cc1101 nicht erkannt wurde - //cc1101::ccFactoryReset(); - EEPROM.write(EE_MAGIC_OFFSET, VERSION_1); - EEPROM.write(EE_MAGIC_OFFSET + 1, VERSION_2); - // if (hascc1101) { // der ccFactoryReset muss auch durchgefuehrt werden, wenn der cc1101 nicht erkannt wurde - //cc1101::ccFactoryReset(); - //} - } - EEPROM.commit(); - EEPROM.end(); +#ifdef CMP_CC1101 + cc1101::ccFactoryReset(); +#endif + + EEPROM.commit(); + } + +#ifdef DEBUG + dumpEEPROM(); +#endif + getFunctions(&musterDec.MSenabled, &musterDec.MUenabled, &musterDec.MCenabled); - +} + +uint8_t cmdstringPos2int(uint8_t pos) { + uint8_t val; + uint8_t hex; + + hex = (uint8_t)cmdstring.charAt(pos); + val = cc1101::hex2int(hex) * 16; + hex = (uint8_t)cmdstring.charAt(pos+1); + val = cc1101::hex2int(hex) + val; + return val; +} + +void printHex2(const byte hex) { // Todo: printf oder scanf nutzen + if (hex < 16) { + MSG_PRINT("0"); + } + MSG_PRINT(hex, HEX); } diff --git a/SIGNALESP/cc1101.h b/SIGNALESP/cc1101.h new file mode 100644 index 0000000..314583a --- /dev/null +++ b/SIGNALESP/cc1101.h @@ -0,0 +1,522 @@ +// cc1101.h + +#ifndef _CC1101_h +#define _CC1101_h + +#if defined(ARDUINO) && ARDUINO >= 100 + #include "Arduino.h" +#else + #include "WProgram.h" +#endif +#include +#include "output.h" + +#ifdef ESP8266 + #include +#endif + +extern String cmdstring; + + + +namespace cc1101 { +#if defined(ARDUINO_AVR_ICT_BOARDS_ICT_BOARDS_AVR_RADINOCC1101) || defined(ESP8266) +// #define SS 8 + #define PIN_MARK433 4 // LOW -> 433Mhz | HIGH -> 868Mhz + #endif + + #define csPin SS // CSN out + #define mosiPin MOSI // MOSI out + #define misoPin MISO // MISO in + #define sckPin SCK // SCLK out + + #ifndef PIN_SEND + #ifdef ARDUINO_AVR_ICT_BOARDS_ICT_BOARDS_AVR_RADINOCC1101 + #define PIN_SEND 9 // gdo0Pin TX out + #define PIN_RECEIVE 7 + #define digitalPinToInterrupt(p) ((p) == 0 ? 2 : ((p) == 1 ? 3 : ((p) == 2 ? 1 : ((p) == 3 ? 0 : ((p) == 7 ? 4 : NOT_AN_INTERRUPT))))) + #else + #define PIN_LED 9 + #define PIN_SEND 3 // gdo0Pin TX out + #define PIN_RECEIVE 2 + #endif + #endif + + + #define CC1101_CONFIG 0x80 + #define CC1101_STATUS 0xC0 + #define CC1100_WRITE_BURST 0x40 + #define CC1100_READ_BURST 0xC0 + + #define CC1100_FREQ2 0x0D // Frequency control word, high byte + #define CC1100_FREQ1 0x0E // Frequency control word, middle byte + #define CC1100_FREQ0 0x0F // Frequency control word, low byte + #define CC1100_PATABLE 0x3E // 8 byte memory + #define CC1100_IOCFG2 0x00 // GDO2 output configuration + #define CC1100_PKTCTRL0 0x08 // Packet config register + + // Status registers + #define CC1100_RSSI 0x34 // Received signal strength indication + #define CC1100_MARCSTATE 0x35 // Control state machine state + + // Strobe commands + #define CC1101_SRES 0x30 // reset + #define CC1100_SFSTXON 0x31 // Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1). + #define CC1100_SCAL 0x33 // Calibrate frequency synthesizer and turn it off + #define CC1100_SRX 0x34 // Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1 + #define CC1100_STX 0x35 // In IDLE state: Enable TX. Perform calibration first if MCSM0.FS_AUTOCAL=1 + #define CC1100_SIDLE 0x36 // Exit RX / TX, turn off frequency synthesizer + #define CC1100_SAFC 0x37 // Perform AFC adjustment of the frequency synthesizer + #define CC1100_SFTX 0x3B // Flush the TX FIFO buffer. + #define CC1101_SNOP 0x3D // + +#ifdef ESP8266 + #define pinAsInput(pin) pinMode(pin, INPUT) + #define pinAsOutput(pin) pinMode(pin, OUTPUT) + #define pinAsInputPullUp(pin) pinMode(pin, INPUT_PULLUP) + + #ifndef digitalLow + #define digitalLow(pin) digitalWrite(pin, LOW) + #endif + #ifndef digitalHigh + #define digitalHigh(pin) digitalWrite(pin, HIGH) + #endif + #ifndef isHigh + #define isHigh(pin) (digitalRead(pin) == HIGH) + #endif +#endif + +#ifndef ESP8266 + #define wait_Miso() while(isHigh(misoPin) ) { static uint8_t miso_count=255;delay(1); if(miso_count==0) return; miso_count--; } // wait until SPI MISO line goes low +#else + #define wait_Miso() while(isHigh(misoPin) ) { static uint8_t miso_count=255;delay(1); if(miso_count==0) break; miso_count--; } // wait until SPI MISO line goes low +#endif + + #define cc1101_Select() digitalLow(csPin) // select (SPI) CC1101 + #define cc1101_Deselect() digitalHigh(csPin) + + #define EE_CC1100_CFG 3 + #define EE_CC1100_CFG_SIZE 0x29 + #define EE_CC1100_PA 0x30 // (EE_CC1100_CFG+EE_CC1100_CFG_SIZE) // 2C + #define EE_CC1100_PA_SIZE 8 + + #define PATABLE_DEFAULT 0x84 // 5 dB default value for factory reset + + //------------------------------------------------------------------------------ + // Chip Status Byte + //------------------------------------------------------------------------------ + + // Bit fields in the chip status byte + #define CC1100_STATUS_CHIP_RDYn_BM 0x80 + #define CC1100_STATUS_STATE_BM 0x70 + #define CC1100_STATUS_FIFO_BYTES_AVAILABLE_BM 0x0F + + // Chip states + #define CC1100_STATE_IDLE 0x00 + #define CC1100_STATE_RX 0x10 + #define CC1100_STATE_TX 0x20 + #define CC1100_STATE_FSTXON 0x30 + #define CC1100_STATE_CALIBRATE 0x40 + #define CC1100_STATE_SETTLING 0x50 + #define CC1100_STATE_RX_OVERFLOW 0x60 + #define CC1100_STATE_TX_UNDERFLOW 0x70 + +#ifdef ARDUINO_AVR_ICT_BOARDS_ICT_BOARDS_AVR_RADINOCC1101 + uint8_t RADINOVARIANT = 0; // Standardwert welcher je radinoVarinat geändert wird +#endif + static const uint8_t initVal[] PROGMEM = + { + // IDX NAME RESET COMMENT + 0x0D, // 00 IOCFG2 29 GDO2 as serial output + 0x2E, // 01 IOCFG1 Tri-State + 0x2D, // 02 IOCFG0 3F GDO0 for input + 0x07, // 03 FIFOTHR + 0xD3, // 04 SYNC1 + 0x91, // 05 SYNC0 + 0x3D, // 06 PKTLEN 0F + 0x04, // 07 PKTCTRL1 + 0x32, // 08 PKTCTRL0 45 + 0x00, // 09 ADDR + 0x00, // 0A CHANNR + 0x06, // 0B FSCTRL1 0F 152kHz IF Frquency + 0x00, // 0C FSCTRL0 + 0x10, // 0D FREQ2 1E Freq + 0xB0, // 0E FREQ1 C4 + 0x71, // 0F FREQ0 EC + 0x57, // 10 MDMCFG4 8C bWidth 325kHz + 0xC4, // 11 MDMCFG3 22 DataRate + 0x30, // 12 MDMCFG2 02 Modulation: ASK + 0x23, // 13 MDMCFG1 22 + 0xb9, // 14 MDMCFG0 F8 ChannelSpace: 350kHz + 0x00, // 15 DEVIATN 47 + 0x07, // 16 MCSM2 07 + 0x00, // 17 MCSM1 30 Bit 3:2 RXOFF_MODE: Select what should happen when a packet has been received: 0 = IDLE 3 = Stay in RX #### + 0x18, // 18 MCSM0 04 Calibration: RX/TX->IDLE + 0x14, // 19 FOCCFG 36 + 0x6C, // 1A BSCFG + 0x07, // 1B AGCCTRL2 03 42 dB instead of 33dB + 0x00, // 1C AGCCTRL1 40 + 0x90, // 1D AGCCTRL0 91 4dB decision boundery + 0x87, // 1E WOREVT1 + 0x6B, // 1F WOREVT0 + 0xF8, // 20 WORCTRL + 0x56, // 21 FREND1 + 0x11, // 22 FREND0 16 0x11 for no PA ramping + 0xE9, // 23 FSCAL3 A9 E9 ?? + 0x2A, // 24 FSCAL2 0A + 0x00, // 25 FSCAL1 20 19 ?? + 0x1F, // 26 FSCAL0 0D + 0x41, // 27 RCCTRL1 + 0x00, // 28 RCCTRL0 + }; + + byte hex2int(byte hex) { // convert a hexdigit to int // Todo: printf oder scanf nutzen + if (hex >= '0' && hex <= '9') hex = hex - '0'; + else if (hex >= 'a' && hex <= 'f') hex = hex - 'a' + 10; + else if (hex >= 'A' && hex <= 'F') hex = hex - 'A' + 10; + return hex; + // printf ("%d\n",$hex) ?? + } + + void printHex2(const byte hex) { // Todo: printf oder scanf nutzen + if (hex < 16) { + MSG_PRINT("0"); + } + // char hexstr[2] = {0}; + //sprintf(hexstr, "%02X", hex); + + MSG_PRINT(hex, HEX); + } + + uint8_t sendSPI(const uint8_t val) { // send byte via SPI + #ifndef ESP8266 + SPDR = val; // transfer byte via SPI + while (!(SPSR & _BV(SPIF))); // wait until SPI operation is terminated + return SPDR; + #else + return SPI.transfer(val); + #endif + } + + uint8_t cmdStrobe(const uint8_t cmd) { // send command strobe to the CC1101 IC via SPI + #ifndef ESP8266 + cc1101_Select(); // select CC1101 + wait_Miso(); // wait until MISO goes low + #endif + uint8_t ret = sendSPI(cmd); // send strobe command + #ifndef ESP8266 + wait_Miso(); // wait until MISO goes low + cc1101_Deselect(); // deselect CC1101 + #endif + return ret; // Chip Status Byte + } + + uint8_t readReg(const uint8_t regAddr, const uint8_t regType) { // read CC1101 register via SPI + cc1101_Select(); // select CC1101 + wait_Miso(); // wait until MISO goes low + sendSPI(regAddr | regType); // send register address + uint8_t val = sendSPI(0x00); // read result + cc1101_Deselect(); // deselect CC1101 + return val; + } + + void writeReg(const uint8_t regAddr, const uint8_t val) { // write single register into the CC1101 IC via SPI + cc1101_Select(); // select CC1101 + wait_Miso(); // wait until MISO goes low + sendSPI(regAddr); // send register address + sendSPI(val); // send value + cc1101_Deselect(); // deselect CC1101 + } + + void readPatable(void) { + uint8_t PatableArray[8]; + // das PatableArray wird zum zwischenspeichern der PATABLE verwendet, + // da ich mir nicht sicher bin ob es timing maessig passt, wenn es nach jedem sendSPI(0x00) eine kurze Pause beim msgprint gibt. + + cc1101_Select(); // select CC1101 + wait_Miso(); // wait until MISO goes low + sendSPI(CC1100_PATABLE | CC1100_READ_BURST); // send register address + for (uint8_t i = 0; i < 8; i++) { + PatableArray[i] = sendSPI(0x00); // read result + } + cc1101_Deselect(); + + for (uint8_t i = 0; i < 8; i++) { + printHex2(PatableArray[i]); + MSG_PRINT(" "); + } + MSG_PRINTLN(""); + } + + void writePatable(void) { + cc1101_Select(); // select CC1101 + wait_Miso(); // wait until MISO goes low + sendSPI(CC1100_PATABLE | CC1100_WRITE_BURST); // send register address + for (uint8_t i = 0; i < 8; i++) { + sendSPI(EEPROM.read(EE_CC1100_PA+i)); // send value + } + cc1101_Deselect(); + } + + + void readCCreg(const uint8_t reg) { // read CC11001 register + uint8_t var; + uint8_t hex; + uint8_t n; + + if (cmdstring.charAt(3) == 'n' && isHexadecimalDigit(cmdstring.charAt(4))) { // Cn gibt anz+2 fortlaufende register zurueck + hex = (uint8_t)cmdstring.charAt(4); + n = hex2int(hex); + if (reg < 0x2F) { + MSG_PRINT("C"); + printHex2(reg); + MSG_PRINT("n"); + n += 2; + printHex2(n); + MSG_PRINT("="); + for (uint8_t i = 0; i < n; i++) { + var = readReg(reg + i, CC1101_CONFIG); + printHex2(var); + } + MSG_PRINTLN(""); + } + } else { + if (reg < 0x3E) { + if (reg < 0x2F) { + var = readReg(reg, CC1101_CONFIG); + } else { + var = readReg(reg, CC1101_STATUS); + } + MSG_PRINT("C"); + printHex2(reg); + MSG_PRINT(" = "); + printHex2(var); + MSG_PRINTLN(""); + } else if (reg == 0x3E) { // patable + MSG_PRINT(F("C3E = ")); + readPatable(); + } else if (reg == 0x99) { // alle register + for (uint8_t i = 0; i < 0x2f; i++) { + if (i == 0 || i == 0x10 || i == 0x20) { + if (i > 0) { + MSG_PRINT(" "); + } + MSG_PRINT(F("ccreg ")); + printHex2(i); + MSG_PRINT(F(": ")); + } + var = readReg(i, CC1101_CONFIG); + printHex2(var); + MSG_PRINT(" "); + } + MSG_PRINTLN(""); + } + } + } + + void commandStrobes(void) { + uint8_t hex; + uint8_t reg; + uint8_t val; + uint8_t val1; + + if (isHexadecimalDigit(cmdstring.charAt(3))) { + hex = (uint8_t)cmdstring.charAt(3); + reg = hex2int(hex) + 0x30; + if (reg < 0x3e) { + val = cmdStrobe(reg); + delay(1); + val1 = cmdStrobe(0x3D); // No operation. May be used to get access to the chip status byte. + MSG_PRINT(F("cmdStrobeReg ")); + printHex2(reg); + MSG_PRINT(F(" chipStatus ")); + val = val >> 4; + MSG_PRINT(val, HEX); + MSG_PRINT(F(" delay1 ")); + val = val1 >> 4; + MSG_PRINT(val, HEX); + MSG_PRINTLN(""); + } + } + } + + void writeCCreg(uint8_t reg, uint8_t var) { // write CC11001 register + if (reg > 1 && reg < 0x40) { + writeReg(reg-2, var); + MSG_PRINT("W"); + printHex2(reg); + printHex2(var); + MSG_PRINTLN(""); + } + } + + void writeCCpatable(uint8_t var) { // write 8 byte to patable (kein pa ramping) + for (uint8_t i = 0; i < 8; i++) { + if (i == 1) { + EEPROM.write(EE_CC1100_PA + i, var); + } else { + EEPROM.write(EE_CC1100_PA + i, 0); + } + } + writePatable(); + } + + void ccFactoryReset() { + for (uint8_t i = 0; i + +#ifndef ESP8266 + SPCR = _BV(SPE) | _BV(MSTR); // SPI speed = CLK/4 + /* + SPCR = ((1 << SPE) | // SPI Enable + (0 << SPIE) | // SPI Interupt Enable + (0 << DORD) | // Data Order (0:MSB first / 1:LSB first) + (1 << MSTR) | // Master/Slave select + (0 << SPR1) | (0 << SPR0) | // SPI Clock Rate + (0 << CPOL) | // Clock Polarity (0:SCK low / 1:SCK hi when idle) + (0 << CPHA)); // Clock Phase (0:leading / 1:trailing edge sampling) + + SPSR = (1 << SPI2X); // Double Clock Rate + */ +#else + SPI.setDataMode(SPI_MODE0); + SPI.setBitOrder(MSBFIRST); + SPI.begin(); + SPI.setClockDivider(SPI_CLOCK_DIV4); +#endif + + pinAsInput(PIN_SEND); // gdo0Pi, sicherheitshalber bis zum CC1101 init erstmal input +#ifndef ESP8266 + digitalHigh(csPin); // SPI init + digitalHigh(sckPin); + digitalLow(mosiPin); +#endif + } + + uint8_t getRSSI() + { + return readReg(CC1100_RSSI, CC1101_STATUS);// Pruefen ob Umwandung von uint to int den richtigen Wert zurueck gibt + } + + inline void setIdleMode() + { + cmdStrobe(CC1100_SIDLE); // Idle mode + delay(1); + } + + uint8_t currentMode() { + return (cmdStrobe(CC1101_SNOP) & CC1100_STATUS_STATE_BM); + } + + void setReceiveMode() + { + setIdleMode(); + uint8_t maxloop = 0xff; + + while (maxloop-- && (cmdStrobe(CC1100_SRX) & CC1100_STATUS_STATE_BM) != CC1100_STATE_RX) // RX enable + delay(1); + if (maxloop == 0 ) DBG_PRINTLN("CC1101: Setting RX failed"); + + } + + void setTransmitMode() + { + cmdStrobe(CC1100_SFTX); // wird dies benoetigt? Wir verwenden kein FIFO + setIdleMode(); + uint8_t maxloop = 0xff; + while (maxloop-- && (cmdStrobe(CC1100_STX) & CC1100_STATUS_STATE_BM) != CC1100_STATE_TX) // TX enable + delay(1); + if (maxloop == 0) DBG_PRINTLN("CC1101: Setting TX failed"); + } + + void CCinit(void) { // initialize CC1101 + + cc1101_Deselect(); // some deselect and selects to init the cc1101 + delayMicroseconds(30); + + // Begin of power on reset + cc1101_Select(); + delayMicroseconds(30); + + cc1101_Deselect(); + delayMicroseconds(45); + + DBG_PRINTLN("SRES Started"); + cmdStrobe(CC1101_SRES); // send reset + DBG_PRINTLN("POR Done"); + delay(10); + + cc1101_Select(); + + sendSPI(CC1100_WRITE_BURST); + for (uint8_t i = 0; i0) { //Puffer auslesen und an Dekoder uebergeben aktVal = FiFo.dequeue(); state = musterDec.decode(&aktVal); if (state) blinkLED = true; //LED blinken, wenn Meldung dekodiert - yield(); } if (Serial.available()) { - int16_t sDuration = 620; - switch(Serial.read()) { - case 'b': - FiFo.enqueue(sDuration); - for (uint8_t i=0; i<55; i++) { - FiFo.enqueue(-sDuration*2); - FiFo.enqueue(sDuration); - } - FiFo.enqueue(-sDuration); - break; case 'c': - Serial.println("currentMode: 0x" + String(cc1101::currentMode(), HEX)); + Serial.println("marc: 0x" + String(cc1101::currentMode(), HEX)); + Serial.println("fifo: " + String(FiFo.count()) + ", max. " + String(fifousage)); break; case 'd': dumpEEPROM(); @@ -295,22 +284,20 @@ void ICACHE_RAM_ATTR handleInterrupt() { } void enableReceive() { - attachInterrupt(PIN_RECEIVE, handleInterrupt, CHANGE); + attachInterrupt(digitalPinToInterrupt(PIN_RECEIVE), handleInterrupt, CHANGE); #ifdef CMP_CC1101 if (hasCC1101) cc1101::setReceiveMode(); - Serial.println("receiver enabled!"); #endif } void disableReceive() { - detachInterrupt(PIN_RECEIVE); + detachInterrupt(digitalPinToInterrupt(PIN_RECEIVE)); #ifdef CMP_CC1101 if (hasCC1101) cc1101::setIdleMode(); - Serial.println("receiver disabled!"); #endif } @@ -319,8 +306,6 @@ void disableReceive() { //================================= RAW Send ====================================== void send_raw(const uint8_t startpos, const uint16_t endpos, const int16_t *buckets, String *source = &cmdstring) { - pinMode(PIN_SEND, OUTPUT); - uint8_t index = 0; unsigned long stoptime = micros(); bool isLow; @@ -350,8 +335,6 @@ void send_raw(const uint8_t startpos, const uint16_t endpos, const int16_t *buck void send_mc(const uint8_t startpos, const uint8_t endpos, const int16_t clock) { - pinMode(PIN_SEND, OUTPUT); - int8_t b; char c; //digitalHigh(PIN_SEND); @@ -410,8 +393,6 @@ struct s_sendcmd { void send_cmd() { - pinMode(PIN_SEND, OUTPUT); - #define combined 0 #define manchester 1 #define raw 2 @@ -734,7 +715,6 @@ inline void ethernetEvent() // newClient.stop(); } yield(); - } void serialEvent() diff --git a/SIGNALESP/cc1101.h b/SIGNALESP/cc1101.h index 314583a..f36114c 100644 --- a/SIGNALESP/cc1101.h +++ b/SIGNALESP/cc1101.h @@ -32,21 +32,21 @@ namespace cc1101 { #ifndef PIN_SEND #ifdef ARDUINO_AVR_ICT_BOARDS_ICT_BOARDS_AVR_RADINOCC1101 - #define PIN_SEND 9 // gdo0Pin TX out #define PIN_RECEIVE 7 #define digitalPinToInterrupt(p) ((p) == 0 ? 2 : ((p) == 1 ? 3 : ((p) == 2 ? 1 : ((p) == 3 ? 0 : ((p) == 7 ? 4 : NOT_AN_INTERRUPT))))) #else - #define PIN_LED 9 - #define PIN_SEND 3 // gdo0Pin TX out - #define PIN_RECEIVE 2 + #define PIN_RECEIVE 5 + #define PIN_SEND 4 // gdo0Pin TX out #endif #endif - #define CC1101_CONFIG 0x80 - #define CC1101_STATUS 0xC0 - #define CC1100_WRITE_BURST 0x40 - #define CC1100_READ_BURST 0xC0 + #define CC1100_WRITE_BURST 0x40 + #define CC1101_WRITE_SINGLE 0x00 + #define CC1100_READ_BURST 0xC0 + #define CC1101_READ_SINGLE 0x80 + #define CC1101_CONFIG CC1101_READ_SINGLE + #define CC1101_STATUS CC1100_READ_BURST #define CC1100_FREQ2 0x0D // Frequency control word, high byte #define CC1100_FREQ1 0x0E // Frequency control word, middle byte @@ -55,9 +55,11 @@ namespace cc1101 { #define CC1100_IOCFG2 0x00 // GDO2 output configuration #define CC1100_PKTCTRL0 0x08 // Packet config register - // Status registers - #define CC1100_RSSI 0x34 // Received signal strength indication - #define CC1100_MARCSTATE 0x35 // Control state machine state + // Status registers - older version base on 0x30 + #define CC1101_PARTNUM 0xF0 // Chip ID + #define CC1101_VERSION 0xF1 // Chip ID + #define CC1100_RSSI 0xF4 // Received signal strength indication + #define CC1100_MARCSTATE 0xF5 // Control state machine state // Strobe commands #define CC1101_SRES 0x30 // reset @@ -68,8 +70,34 @@ namespace cc1101 { #define CC1100_SIDLE 0x36 // Exit RX / TX, turn off frequency synthesizer #define CC1100_SAFC 0x37 // Perform AFC adjustment of the frequency synthesizer #define CC1100_SFTX 0x3B // Flush the TX FIFO buffer. - #define CC1101_SNOP 0x3D // - + #define CC1101_SNOP 0x3D // + + enum CC1101_MarcState { + MarcStateSleep = 0x00u + , MarcStateIdle = 0x01u + , MarcStateXOff = 0x02u + , MarcStateVConnManCal = 0x03u + , MarcStateRegOnManCal = 0x04u + , MarcStateManCal = 0x05u + , MarcStateVConnFSWakeUp = 0x06u + , MarcStateRegOnFSWakeUp = 0x07u + , MarcStateStartCalibrate = 0x08u + , MarcStateBWBoost = 0x09u + , MarcStateFSLock = 0x0Au + , MarcStateIfadCon = 0x0Bu + , MarcStateEndCalibrate = 0x0Cu + , MarcStateRx = 0x0Du + , MarcStateRxEnd = 0x0Eu + , MarcStateRxRst = 0x0Fu + , MarcStateTxRxSwitch = 0x10u + , MarcStateRxFifoOverflow = 0x11u + , MarcStateFsTxOn = 0x12u + , MarcStateTx = 0x13u + , MarcStateTxEnd = 0x14u + , MarcStateRxTxSwitch = 0x15u + , MarcStateTxFifoUnerflow = 0x16u + }; + #ifdef ESP8266 #define pinAsInput(pin) pinMode(pin, INPUT) #define pinAsOutput(pin) pinMode(pin, OUTPUT) @@ -122,7 +150,7 @@ namespace cc1101 { #define CC1100_STATE_TX_UNDERFLOW 0x70 #ifdef ARDUINO_AVR_ICT_BOARDS_ICT_BOARDS_AVR_RADINOCC1101 - uint8_t RADINOVARIANT = 0; // Standardwert welcher je radinoVarinat geändert wird + uint8_t RADINOVARIANT = 0; // Standardwert welcher je radinoVarinat ge�ndert wird #endif static const uint8_t initVal[] PROGMEM = { @@ -199,15 +227,11 @@ namespace cc1101 { } uint8_t cmdStrobe(const uint8_t cmd) { // send command strobe to the CC1101 IC via SPI - #ifndef ESP8266 cc1101_Select(); // select CC1101 wait_Miso(); // wait until MISO goes low - #endif uint8_t ret = sendSPI(cmd); // send strobe command - #ifndef ESP8266 wait_Miso(); // wait until MISO goes low cc1101_Deselect(); // deselect CC1101 - #endif return ret; // Chip Status Byte } @@ -378,10 +402,10 @@ namespace cc1101 { bool checkCC1101() { - uint8_t partnum = readReg(0xF0,0x80); // Partnum - uint8_t version = readReg(0xF1,0x80); // Version - DBG_PRINT("CCVersion="); DBG_PRINTLN(version); - DBG_PRINT("CCPartnum="); DBG_PRINTLN(partnum); + uint8_t partnum = readReg(CC1101_PARTNUM, CC1101_READ_SINGLE); // Partnum + uint8_t version = readReg(CC1101_VERSION, CC1101_READ_SINGLE); // Version + DBG_PRINT("CCVersion="); DBG_PRINTLN("0x" + String(version, HEX)); + DBG_PRINT("CCPartnum="); DBG_PRINTLN("0x" + String(partnum, HEX)); //checks if valid Chip ID is found. Usualy 0x03 or 0x14. if not -> abort if (version == 0x00 || version == 0xFF) @@ -407,7 +431,7 @@ namespace cc1101 { #ifdef ARDUINO_AVR_ICT_BOARDS_ICT_BOARDS_AVR_RADINOCC1101 pinAsInputPullUp(PIN_MARK433); #endif - //// Änderungsbeginn ---> + //// �nderungsbeginn ---> #ifndef ESP8266 SPCR = _BV(SPE) | _BV(MSTR); // SPI speed = CLK/4 @@ -429,12 +453,14 @@ namespace cc1101 { SPI.setClockDivider(SPI_CLOCK_DIV4); #endif - pinAsInput(PIN_SEND); // gdo0Pi, sicherheitshalber bis zum CC1101 init erstmal input #ifndef ESP8266 digitalHigh(csPin); // SPI init digitalHigh(sckPin); digitalLow(mosiPin); #endif + + pinAsInput(PIN_RECEIVE); // gdo2 + pinAsOutput(PIN_SEND); // gdo0Pi, sicherheitshalber bis zum CC1101 init erstmal input } uint8_t getRSSI() @@ -449,7 +475,7 @@ namespace cc1101 { } uint8_t currentMode() { - return (cmdStrobe(CC1101_SNOP) & CC1100_STATUS_STATE_BM); + return readReg(CC1100_MARCSTATE, CC1100_READ_BURST); } void setReceiveMode() From abad781d9cc87d2cc32644bb9bcedaea77901ffa Mon Sep 17 00:00:00 2001 From: habeIchVergessen Date: Fri, 18 Aug 2017 10:23:59 +0200 Subject: [PATCH 03/40] version output --- SIGNALESP/SIGNALESP.ino | 37 ++++++++++++++++++++++++++++++++++++- SIGNALESP/cc1101.h | 4 ++-- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/SIGNALESP/SIGNALESP.ino b/SIGNALESP/SIGNALESP.ino index ad40cb9..bf5f8b2 100644 --- a/SIGNALESP/SIGNALESP.ino +++ b/SIGNALESP/SIGNALESP.ino @@ -256,6 +256,9 @@ void loop() { case 'd': dumpEEPROM(); break; + case 'u': + Serial.println("uptime: " + uptime()); + break; } } } @@ -548,8 +551,19 @@ void HandleCommand() else if (cmdstring.charAt(0) == cmd_Version) { MSG_PRINT("V " PROGVERS " SIGNALESP "); #ifdef CMP_CC1101 - if (hasCC1101) + if (hasCC1101) { MSG_PRINT(F("cc1101")); + switch(cc1101::chipVersion()) { +// case 0x08: // CC1101_VERSION 0x31 + case 0x18: // CC1101_VERSION 0xF1 + MSG_PRINT(F(" 433MHz")); + break; + case 0x04: // CC1101_VERSION 0x31 + case 0x14: // CC1101_VERSION 0xF1 + MSG_PRINT(F(" 868MHz")); + break; + } + } #endif MSG_PRINTLN(" - compiled at " __DATE__ " " __TIME__); } @@ -855,3 +869,24 @@ void printHex2(const byte hex) { // Todo: printf oder scanf nutzen } MSG_PRINT(hex, HEX); } + +String uptime() { + String result = ""; + + unsigned long uptime = (millis() / 1000); + + uint8_t uptimeDays = uptime / 86400; + if (uptimeDays > 0) + result += String(uptimeDays) + "d, "; + uptime %= 86400; + uint8_t hours = uptime / 3600; + result += String(hours < 10 ? String("0") + hours : hours) + ":"; + uptime %= 3600; + uint8_t minutes = uptime / 60; + result += String(minutes < 10 ? String("0") + minutes : minutes) + "."; + uptime %= 60; + result += String(uptime < 10 ? String("0") + uptime : uptime); + + return result; +} + diff --git a/SIGNALESP/cc1101.h b/SIGNALESP/cc1101.h index f36114c..80c050b 100644 --- a/SIGNALESP/cc1101.h +++ b/SIGNALESP/cc1101.h @@ -399,11 +399,11 @@ namespace cc1101 { MSG_PRINTLN("ccFactoryReset done"); } - + uint8_t chipVersion() { return readReg(CC1101_VERSION, CC1101_READ_SINGLE); }; bool checkCC1101() { uint8_t partnum = readReg(CC1101_PARTNUM, CC1101_READ_SINGLE); // Partnum - uint8_t version = readReg(CC1101_VERSION, CC1101_READ_SINGLE); // Version + uint8_t version = chipVersion(); // Version DBG_PRINT("CCVersion="); DBG_PRINTLN("0x" + String(version, HEX)); DBG_PRINT("CCPartnum="); DBG_PRINTLN("0x" + String(partnum, HEX)); From c9cc80eb5b32124c7615b6308674d35e56f857d3 Mon Sep 17 00:00:00 2001 From: habeIchVergessen Date: Fri, 18 Aug 2017 10:51:56 +0200 Subject: [PATCH 04/40] fix travis error --- SIGNALESP/cc1101.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/SIGNALESP/cc1101.h b/SIGNALESP/cc1101.h index 80c050b..106fb0a 100644 --- a/SIGNALESP/cc1101.h +++ b/SIGNALESP/cc1101.h @@ -8,11 +8,11 @@ #else #include "WProgram.h" #endif -#include +#include "EEPROM.h" #include "output.h" #ifdef ESP8266 - #include + #include "SPI.h" #endif extern String cmdstring; @@ -21,9 +21,11 @@ extern String cmdstring; namespace cc1101 { #if defined(ARDUINO_AVR_ICT_BOARDS_ICT_BOARDS_AVR_RADINOCC1101) || defined(ESP8266) -// #define SS 8 + #ifndef ESP8266 + #define SS 8 + #endif #define PIN_MARK433 4 // LOW -> 433Mhz | HIGH -> 868Mhz - #endif +#endif #define csPin SS // CSN out #define mosiPin MOSI // MOSI out From 2ab341545f084a678a7150da5e65b683f7bf0862 Mon Sep 17 00:00:00 2001 From: habeIchVergessen Date: Fri, 18 Aug 2017 11:25:59 +0200 Subject: [PATCH 05/40] fix travis errors --- SIGNALESP/SIGNALESP.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/SIGNALESP/SIGNALESP.ino b/SIGNALESP/SIGNALESP.ino index bf5f8b2..785941f 100644 --- a/SIGNALESP/SIGNALESP.ino +++ b/SIGNALESP/SIGNALESP.ino @@ -36,6 +36,7 @@ SignalDetectorClass musterDec; #ifdef CMP_CC1101 #include "cc1101.h" + #include "SPI.h" // prevent travis errors #endif #define pulseMin 90 From 2e20e64faeb24d4e04161a177e266cb052622876 Mon Sep 17 00:00:00 2001 From: habeIchVergessen Date: Fri, 18 Aug 2017 11:37:46 +0200 Subject: [PATCH 06/40] fix travis errors --- SIGNALESP/SIGNALESP.ino | 2 +- SIGNALESP/cc1101.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/SIGNALESP/SIGNALESP.ino b/SIGNALESP/SIGNALESP.ino index 785941f..6ce04a7 100644 --- a/SIGNALESP/SIGNALESP.ino +++ b/SIGNALESP/SIGNALESP.ino @@ -36,7 +36,7 @@ SignalDetectorClass musterDec; #ifdef CMP_CC1101 #include "cc1101.h" - #include "SPI.h" // prevent travis errors + #include // prevent travis errors #endif #define pulseMin 90 diff --git a/SIGNALESP/cc1101.h b/SIGNALESP/cc1101.h index 106fb0a..c4f60e8 100644 --- a/SIGNALESP/cc1101.h +++ b/SIGNALESP/cc1101.h @@ -8,11 +8,11 @@ #else #include "WProgram.h" #endif -#include "EEPROM.h" +#include #include "output.h" #ifdef ESP8266 - #include "SPI.h" + #include #endif extern String cmdstring; From c71b56b1602c710d9151c0e72e6eacdee8de4ffb Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Fri, 18 Aug 2017 22:59:33 +0200 Subject: [PATCH 07/40] removed old cc1101.h --- cc1101.h | 476 ------------------------------------------------------- 1 file changed, 476 deletions(-) delete mode 100644 cc1101.h diff --git a/cc1101.h b/cc1101.h deleted file mode 100644 index 8001532..0000000 --- a/cc1101.h +++ /dev/null @@ -1,476 +0,0 @@ -// cc1101.h - -#ifndef _CC1101_h -#define _CC1101_h - -#if defined(ARDUINO) && ARDUINO >= 100 - #include "Arduino.h" -#else - #include "WProgram.h" -#endif -#include -#include "output.h" - - -extern String cmdstring; - - - -namespace cc1101 { - #ifdef ARDUINO_AVR_ICT_BOARDS_ICT_BOARDS_AVR_RADINOCC1101 - #define SS 8 - #define PIN_MARK433 4 // LOW -> 433Mhz | HIGH -> 868Mhz - #endif - - #define csPin SS // CSN out - #define mosiPin MOSI // MOSI out - #define misoPin MISO // MISO in - #define sckPin SCK // SCLK out - - - #define CC1101_CONFIG 0x80 - #define CC1101_STATUS 0xC0 - #define CC1100_WRITE_BURST 0x40 - #define CC1100_READ_BURST 0xC0 - - #define CC1100_FREQ2 0x0D // Frequency control word, high byte - #define CC1100_FREQ1 0x0E // Frequency control word, middle byte - #define CC1100_FREQ0 0x0F // Frequency control word, low byte - #define CC1100_PATABLE 0x3E // 8 byte memory - #define CC1100_IOCFG2 0x00 // GDO2 output configuration - #define CC1100_PKTCTRL0 0x08 // Packet config register - - // Status registers - #define CC1100_RSSI 0x34 // Received signal strength indication - #define CC1100_MARCSTATE 0x35 // Control state machine state - - // Strobe commands - #define CC1101_SRES 0x30 // reset - #define CC1100_SFSTXON 0x31 // Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1). - #define CC1100_SCAL 0x33 // Calibrate frequency synthesizer and turn it off - #define CC1100_SRX 0x34 // Enable RX. Perform calibration first if coming from IDLE and MCSM0.FS_AUTOCAL=1 - #define CC1100_STX 0x35 // In IDLE state: Enable TX. Perform calibration first if MCSM0.FS_AUTOCAL=1 - #define CC1100_SIDLE 0x36 // Exit RX / TX, turn off frequency synthesizer - #define CC1100_SAFC 0x37 // Perform AFC adjustment of the frequency synthesizer - #define CC1100_SFTX 0x3B // Flush the TX FIFO buffer. - - #define wait_Miso() while(isHigh(misoPin) ) { static uint8_t miso_count=255;delay(1); if(miso_count==0) return; miso_count--; } // wait until SPI MISO line goes low - #define cc1101_Select() digitalLow(csPin) // select (SPI) CC1101 - #define cc1101_Deselect() digitalHigh(csPin) - - #define EE_CC1100_CFG 2 - #define EE_CC1100_CFG_SIZE 0x29 - #define EE_CC1100_PA 0x30 // (EE_CC1100_CFG+EE_CC1100_CFG_SIZE) // 2B - #define EE_CC1100_PA_SIZE 8 - - #define PATABLE_DEFAULT 0x84 // 5 dB default value for factory reset - - //------------------------------------------------------------------------------ - // Chip Status Byte - //------------------------------------------------------------------------------ - - // Bit fields in the chip status byte - #define CC1100_STATUS_CHIP_RDYn_BM 0x80 - #define CC1100_STATUS_STATE_BM 0x70 - #define CC1100_STATUS_FIFO_BYTES_AVAILABLE_BM 0x0F - - // Chip states - #define CC1100_STATE_IDLE 0x00 - #define CC1100_STATE_RX 0x10 - #define CC1100_STATE_TX 0x20 - #define CC1100_STATE_FSTXON 0x30 - #define CC1100_STATE_CALIBRATE 0x40 - #define CC1100_STATE_SETTLING 0x50 - #define CC1100_STATE_RX_OVERFLOW 0x60 - #define CC1100_STATE_TX_UNDERFLOW 0x70 - - - #ifdef ARDUINO_AVR_ICT_BOARDS_ICT_BOARDS_AVR_RADINOCC1101 - uint8_t RADINOVARIANT = 0; // Standardwert welcher je radinoVarinat geändert wird - #endif - static const uint8_t initVal[] PROGMEM = - { - // IDX NAME RESET COMMENT - 0x0D, // 00 IOCFG2 29 GDO2 as serial output - 0x2E, // 01 IOCFG1 Tri-State - 0x2D, // 02 IOCFG0 3F GDO0 for input - 0x07, // 03 FIFOTHR - 0xD3, // 04 SYNC1 - 0x91, // 05 SYNC0 - 0x3D, // 06 PKTLEN 0F - 0x04, // 07 PKTCTRL1 - 0x32, // 08 PKTCTRL0 45 - 0x00, // 09 ADDR - 0x00, // 0A CHANNR - 0x06, // 0B FSCTRL1 0F 152kHz IF Frquency - 0x00, // 0C FSCTRL0 - 0x10, // 0D FREQ2 1E Freq - 0xB0, // 0E FREQ1 C4 - 0x71, // 0F FREQ0 EC - 0x57, // 10 MDMCFG4 8C bWidth 325kHz - 0xC4, // 11 MDMCFG3 22 DataRate - 0x30, // 12 MDMCFG2 02 Modulation: ASK - 0x23, // 13 MDMCFG1 22 - 0xb9, // 14 MDMCFG0 F8 ChannelSpace: 350kHz - 0x00, // 15 DEVIATN 47 - 0x07, // 16 MCSM2 07 - 0x00, // 17 MCSM1 30 Bit 3:2 RXOFF_MODE: Select what should happen when a packet has been received: 0 = IDLE 3 = Stay in RX #### - 0x18, // 18 MCSM0 04 Calibration: RX/TX->IDLE - 0x14, // 19 FOCCFG 36 - 0x6C, // 1A BSCFG - 0x07, // 1B AGCCTRL2 03 42 dB instead of 33dB - 0x00, // 1C AGCCTRL1 40 - 0x90, // 1D AGCCTRL0 91 4dB decision boundery - 0x87, // 1E WOREVT1 - 0x6B, // 1F WOREVT0 - 0xF8, // 20 WORCTRL - 0x56, // 21 FREND1 - 0x11, // 22 FREND0 16 0x11 for no PA ramping - 0xE9, // 23 FSCAL3 A9 E9 ?? - 0x2A, // 24 FSCAL2 0A - 0x00, // 25 FSCAL1 20 19 ?? - 0x1F, // 26 FSCAL0 0D - 0x41, // 27 RCCTRL1 - 0x00, // 28 RCCTRL0 - }; - - byte hex2int(byte hex) { // convert a hexdigit to int // Todo: printf oder scanf nutzen - if (hex >= '0' && hex <= '9') hex = hex - '0'; - else if (hex >= 'a' && hex <= 'f') hex = hex - 'a' + 10; - else if (hex >= 'A' && hex <= 'F') hex = hex - 'A' + 10; - return hex; - // printf ("%d\n",$hex) ?? - } - - void printHex2(const byte hex) { // Todo: printf oder scanf nutzen - if (hex < 16) { - MSG_PRINT("0"); - } - // char hexstr[2] = {0}; - //sprintf(hexstr, "%02X", hex); - - MSG_PRINT(hex, HEX); - - - } - - - uint8_t sendSPI(const uint8_t val) { // send byte via SPI - SPDR = val; // transfer byte via SPI - while (!(SPSR & _BV(SPIF))); // wait until SPI operation is terminated - return SPDR; - } - - uint8_t cmdStrobe(const uint8_t cmd) { // send command strobe to the CC1101 IC via SPI - cc1101_Select(); // select CC1101 - wait_Miso(); // wait until MISO goes low - uint8_t ret = sendSPI(cmd); // send strobe command - wait_Miso(); // wait until MISO goes low - cc1101_Deselect(); // deselect CC1101 - return ret; // Chip Status Byte - } - - uint8_t readReg(const uint8_t regAddr, const uint8_t regType) { // read CC1101 register via SPI - cc1101_Select(); // select CC1101 - wait_Miso(); // wait until MISO goes low - sendSPI(regAddr | regType); // send register address - uint8_t val = sendSPI(0x00); // read result - cc1101_Deselect(); // deselect CC1101 - return val; - } - - void writeReg(const uint8_t regAddr, const uint8_t val) { // write single register into the CC1101 IC via SPI - cc1101_Select(); // select CC1101 - wait_Miso(); // wait until MISO goes low - sendSPI(regAddr); // send register address - sendSPI(val); // send value - cc1101_Deselect(); // deselect CC1101 - } - - void readPatable(void) { - uint8_t PatableArray[8]; - // das PatableArray wird zum zwischenspeichern der PATABLE verwendet, - // da ich mir nicht sicher bin ob es timing maessig passt, wenn es nach jedem sendSPI(0x00) eine kurze Pause beim msgprint gibt. - - cc1101_Select(); // select CC1101 - wait_Miso(); // wait until MISO goes low - sendSPI(CC1100_PATABLE | CC1100_READ_BURST); // send register address - for (uint8_t i = 0; i < 8; i++) { - PatableArray[i] = sendSPI(0x00); // read result - } - cc1101_Deselect(); - - for (uint8_t i = 0; i < 8; i++) { - printHex2(PatableArray[i]); - MSG_PRINT(" "); - } - MSG_PRINTLN(""); - } - - void writePatable(void) { - cc1101_Select(); // select CC1101 - wait_Miso(); // wait until MISO goes low - sendSPI(CC1100_PATABLE | CC1100_WRITE_BURST); // send register address - for (uint8_t i = 0; i < 8; i++) { - sendSPI(EEPROM.read(EE_CC1100_PA+i)); // send value - } - cc1101_Deselect(); - } - - - void readCCreg(const uint8_t reg) { // read CC11001 register - uint8_t var; - uint8_t hex; - uint8_t n; - - if (cmdstring.charAt(3) == 'n' && isHexadecimalDigit(cmdstring.charAt(4))) { // Cn gibt anz+2 fortlaufende register zurueck - hex = (uint8_t)cmdstring.charAt(4); - n = hex2int(hex); - if (reg < 0x2F) { - MSG_PRINT("C"); - printHex2(reg); - MSG_PRINT("n"); - n += 2; - printHex2(n); - MSG_PRINT("="); - for (uint8_t i = 0; i < n; i++) { - var = readReg(reg + i, CC1101_CONFIG); - printHex2(var); - } - MSG_PRINTLN(""); - } - } - else { - if (reg < 0x3E) { - if (reg < 0x2F) { - var = readReg(reg, CC1101_CONFIG); - } - else { - var = readReg(reg, CC1101_STATUS); - } - MSG_PRINT("C"); - printHex2(reg); - MSG_PRINT(" = "); - printHex2(var); - MSG_PRINTLN(""); - } - else if (reg == 0x3E) { // patable - MSG_PRINT(F("C3E = ")); - readPatable(); - } - else if (reg == 0x99) { // alle register - for (uint8_t i = 0; i < 0x2f; i++) { - if (i == 0 || i == 0x10 || i == 0x20) { - if (i > 0) { - MSG_PRINT(" "); - } - MSG_PRINT(F("ccreg ")); - printHex2(i); - MSG_PRINT(F(": ")); - } - var = readReg(i, CC1101_CONFIG); - printHex2(var); - MSG_PRINT(" "); - } - MSG_PRINTLN(""); - } - } - } - - void commandStrobes(void) { - uint8_t hex; - uint8_t reg; - uint8_t val; - uint8_t val1; - - if (isHexadecimalDigit(cmdstring.charAt(3))) { - hex = (uint8_t)cmdstring.charAt(3); - reg = hex2int(hex) + 0x30; - if (reg < 0x3e) { - val = cmdStrobe(reg); - delay(1); - val1 = cmdStrobe(0x3D); // No operation. May be used to get access to the chip status byte. - MSG_PRINT(F("cmdStrobeReg ")); - printHex2(reg); - MSG_PRINT(F(" chipStatus ")); - val = val >> 4; - MSG_PRINT(val, HEX); - MSG_PRINT(F(" delay1 ")); - val = val1 >> 4; - MSG_PRINT(val, HEX); - MSG_PRINTLN(""); - } - } - } - - - void writeCCreg(uint8_t reg, uint8_t var) { // write CC11001 register - - if (reg > 1 && reg < 0x40) { - writeReg(reg-2, var); - MSG_PRINT("W"); - printHex2(reg); - printHex2(var); - MSG_PRINTLN(""); - } - } - - -void writeCCpatable(uint8_t var) { // write 8 byte to patable (kein pa ramping) - for (uint8_t i = 0; i < 8; i++) { - if (i == 1) { - EEPROM.write(EE_CC1100_PA + i, var); - } else { - EEPROM.write(EE_CC1100_PA + i, 0); - } - } - writePatable(); -} - - - - - void ccFactoryReset() { - for (uint8_t i = 0; i - - - SPCR = _BV(SPE) | _BV(MSTR); // SPI speed = CLK/4 - /* - SPCR = ((1 << SPE) | // SPI Enable - (0 << SPIE) | // SPI Interupt Enable - (0 << DORD) | // Data Order (0:MSB first / 1:LSB first) - (1 << MSTR) | // Master/Slave select - (0 << SPR1) | (0 << SPR0) | // SPI Clock Rate - (0 << CPOL) | // Clock Polarity (0:SCK low / 1:SCK hi when idle) - (0 << CPHA)); // Clock Phase (0:leading / 1:trailing edge sampling) - - SPSR = (1 << SPI2X); // Double Clock Rate - */ - pinAsInput(PIN_SEND); // gdo0Pi, sicherheitshalber bis zum CC1101 init erstmal input - digitalHigh(csPin); // SPI init - digitalHigh(sckPin); - digitalLow(mosiPin); - } - - uint8_t getRSSI() - { - return readReg(CC1100_RSSI, CC1101_STATUS);// Pruefen ob Umwandung von uint to int den richtigen Wert zurueck gibt - } - - inline void setIdleMode() - { - cmdStrobe(CC1100_SIDLE); // Idle mode - delay(1); - } - - void setReceiveMode() - { - setIdleMode(); - uint8_t maxloop = 0xff; - - while (maxloop-- && (cmdStrobe(CC1100_SRX) & CC1100_STATUS_STATE_BM) != CC1100_STATE_RX) // RX enable - delay(1); - if (maxloop == 0 ) DBG_PRINTLN("CC1101: Setting RX failed"); - - } - - void setTransmitMode() - { - cmdStrobe(CC1100_SFTX); // wird dies benoetigt? Wir verwenden kein FIFO - setIdleMode(); - uint8_t maxloop = 0xff; - while (maxloop-- && (cmdStrobe(CC1100_STX) & CC1100_STATUS_STATE_BM) != CC1100_STATE_TX) // TX enable - delay(1); - if (maxloop == 0) DBG_PRINTLN("CC1101: Setting TX failed"); - } - - void CCinit(void) { // initialize CC1101 - - cc1101_Deselect(); // some deselect and selects to init the cc1101 - delayMicroseconds(30); - - // Begin of power on reset - cc1101_Select(); - delayMicroseconds(30); - - cc1101_Deselect(); - delayMicroseconds(45); - - DBG_PRINTLN("SRES Started"); - cmdStrobe(CC1101_SRES); // send reset - DBG_PRINTLN("POR Done"); - delay(10); - - cc1101_Select(); - - sendSPI(CC1100_WRITE_BURST); - for (uint8_t i = 0; i - + + - + diff --git a/SIGNALESP/__vm/Configuration.Release.vmps.xml b/SIGNALESP/__vm/Configuration.Release.vmps.xml index c2121dc..9a3e5eb 100644 --- a/SIGNALESP/__vm/Configuration.Release.vmps.xml +++ b/SIGNALESP/__vm/Configuration.Release.vmps.xml @@ -1,8 +1,8 @@ - + - + diff --git a/SIGNALESP/cc1101.h b/SIGNALESP/cc1101.h index c4f60e8..b87bf1a 100644 --- a/SIGNALESP/cc1101.h +++ b/SIGNALESP/cc1101.h @@ -20,7 +20,7 @@ extern String cmdstring; namespace cc1101 { -#if defined(ARDUINO_AVR_ICT_BOARDS_ICT_BOARDS_AVR_RADINOCC1101) || defined(ESP8266) +#if defined(ARDUINO_AVR_ICT_BOARDS_ICT_BOARDS_AVR_RADINOCC1101) #ifndef ESP8266 #define SS 8 #endif @@ -32,15 +32,6 @@ namespace cc1101 { #define misoPin MISO // MISO in #define sckPin SCK // SCLK out - #ifndef PIN_SEND - #ifdef ARDUINO_AVR_ICT_BOARDS_ICT_BOARDS_AVR_RADINOCC1101 - #define PIN_RECEIVE 7 - #define digitalPinToInterrupt(p) ((p) == 0 ? 2 : ((p) == 1 ? 3 : ((p) == 2 ? 1 : ((p) == 3 ? 0 : ((p) == 7 ? 4 : NOT_AN_INTERRUPT))))) - #else - #define PIN_RECEIVE 5 - #define PIN_SEND 4 // gdo0Pin TX out - #endif - #endif #define CC1100_WRITE_BURST 0x40 @@ -116,11 +107,7 @@ namespace cc1101 { #endif #endif -#ifndef ESP8266 #define wait_Miso() while(isHigh(misoPin) ) { static uint8_t miso_count=255;delay(1); if(miso_count==0) return; miso_count--; } // wait until SPI MISO line goes low -#else - #define wait_Miso() while(isHigh(misoPin) ) { static uint8_t miso_count=255;delay(1); if(miso_count==0) break; miso_count--; } // wait until SPI MISO line goes low -#endif #define cc1101_Select() digitalLow(csPin) // select (SPI) CC1101 #define cc1101_Deselect() digitalHigh(csPin) From ed910fd5a73c64da7d1e7e215ee50297ba34eaef Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Fri, 18 Aug 2017 23:41:38 +0200 Subject: [PATCH 09/40] Added fastdelegate lib --- .../libraries/fastdelegate/examples/Demo.cpp | 143 + .../libraries/fastdelegate/library.properties | 8 + .../libraries/fastdelegate/src/FastDelegate.h | 2296 +++++++++++++++++ .../fastdelegate/src/FastDelegateBind.h | 243 ++ 4 files changed, 2690 insertions(+) create mode 100644 src/_micro-api/libraries/fastdelegate/examples/Demo.cpp create mode 100644 src/_micro-api/libraries/fastdelegate/library.properties create mode 100644 src/_micro-api/libraries/fastdelegate/src/FastDelegate.h create mode 100644 src/_micro-api/libraries/fastdelegate/src/FastDelegateBind.h diff --git a/src/_micro-api/libraries/fastdelegate/examples/Demo.cpp b/src/_micro-api/libraries/fastdelegate/examples/Demo.cpp new file mode 100644 index 0000000..c3dccf7 --- /dev/null +++ b/src/_micro-api/libraries/fastdelegate/examples/Demo.cpp @@ -0,0 +1,143 @@ +#include +#include "FastDelegate.h" +// Demonstrate the syntax for FastDelegates. +// -Don Clugston, May 2004. +// It's a really boring example, but it shows the most important cases. + +// Declare some functions of varying complexity... +void SimpleStaticFunction(int num, char *str) { + printf("In SimpleStaticFunction. Num=%d, str = %s\n", num, str); +} + +void SimpleVoidFunction() { + printf("In SimpleVoidFunction with no parameters.\n"); +} + +class CBaseClass { +protected: + char *m_name; +public: + CBaseClass(char *name) : m_name(name) {}; + void SimpleMemberFunction(int num, char *str) { + printf("In SimpleMemberFunction in %s. Num=%d, str = %s\n", m_name, num, str); } + int SimpleMemberFunctionReturnsInt(int num, char *str) { + printf("In SimpleMemberFunction in %s. Num=%d, str = %s\n", m_name, num, str); return -1; } + void ConstMemberFunction(int num, char *str) const { + printf("In ConstMemberFunction in %s. Num=%d, str = %s\n", m_name, num, str); } + virtual void SimpleVirtualFunction(int num, char *str) { + printf("In SimpleVirtualFunction in %s. Num=%d, str = %s\n", m_name, num, str); } + static void StaticMemberFunction(int num, char *str) { + printf("In StaticMemberFunction. Num=%d, str =%s\n", num, str); } +}; + +class COtherClass { + double rubbish; // to ensure this class has non-zero size. +public: + virtual void UnusedVirtualFunction(void) { } + virtual void TrickyVirtualFunction(int num, char *str)=0; +}; + +class VeryBigClass { + int letsMakeThingsComplicated[400]; +}; + +// This declaration ensures that we get a convoluted class heirarchy. +class CDerivedClass : public VeryBigClass, virtual public COtherClass, virtual public CBaseClass +{ + double m_somemember[8]; +public: + CDerivedClass() : CBaseClass("Base of Derived") { m_somemember[0]=1.2345; } + void SimpleDerivedFunction(int num, char *str) { printf("In SimpleDerived. num=%d\n", num); } + virtual void AnotherUnusedVirtualFunction(int num, char *str) {} + virtual void TrickyVirtualFunction(int num, char *str) { + printf("In Derived TrickyMemberFunction. Num=%d, str = %s\n", num, str); + } +}; + +using namespace fastdelegate; + +int main(void) +{ + // Delegates with up to 8 parameters are supported. + // Here's the case for a void function. + // We declare a delegate and attach it to SimpleVoidFunction() + printf("-- FastDelegate demo --\nA no-parameter delegate is declared using FastDelegate0\n\n"); + + FastDelegate0<> noparameterdelegate(&SimpleVoidFunction); + + noparameterdelegate(); // invoke the delegate - this calls SimpleVoidFunction() + + printf("\n-- Examples using two-parameter delegates (int, char *) --\n\n"); + + // By default, the return value is void. + typedef FastDelegate2 MyDelegate; + + // If you want to have a non-void return value, put it at the end. + typedef FastDelegate2 IntMyDelegate; + + + MyDelegate funclist[12]; // delegates are initialized to empty + CBaseClass a("Base A"); + CBaseClass b("Base B"); + CDerivedClass d; + CDerivedClass c; + + IntMyDelegate newdeleg; + newdeleg = MakeDelegate(&a, &CBaseClass::SimpleMemberFunctionReturnsInt); + + // Binding a simple member function + funclist[0].bind(&a, &CBaseClass::SimpleMemberFunction); + + // You can also bind static (free) functions + funclist[1].bind(&SimpleStaticFunction); + // and static member functions + funclist[2].bind(&CBaseClass::StaticMemberFunction); + // and const member functions (these only need a const class pointer). + funclist[11].bind( (const CBaseClass *)&a, &CBaseClass::ConstMemberFunction); + funclist[3].bind( &a, &CBaseClass::ConstMemberFunction); + // and virtual member functions + funclist[4].bind(&b, &CBaseClass::SimpleVirtualFunction); + + // You can also use the = operator. For static functions, a fastdelegate + // looks identical to a simple function pointer. + funclist[5] = &CBaseClass::StaticMemberFunction; + + // The weird rule about the class of derived member function pointers is avoided. + // For MSVC, you can use &CDerivedClass::SimpleVirtualFunction here, but DMC will complain. + // Note that as well as .bind(), you can also use the MakeDelegate() + // global function. + funclist[6] = MakeDelegate(&d, &CBaseClass::SimpleVirtualFunction); + + // The worst case is an abstract virtual function of a virtually-derived class + // with at least one non-virtual base class. This is a VERY obscure situation, + // which you're unlikely to encounter in the real world. + // FastDelegate versions prior to 1.3 had problems with this case on VC6. + // Now, it works without problems on all compilers. + funclist[7].bind(&c, &CDerivedClass::TrickyVirtualFunction); + // BUT... in such cases you should be using the base class as an + // interface, anyway. + funclist[8].bind(&c, &COtherClass::TrickyVirtualFunction); + // Calling a function that was first declared in the derived class is straightforward + funclist[9] = MakeDelegate(&c, &CDerivedClass::SimpleDerivedFunction); + + // You can also bind directly using the constructor + MyDelegate dg(&b, &CBaseClass::SimpleVirtualFunction); + + char *msg = "Looking for equal delegate"; + for (int i=0; i<12; i++) { + printf("%d :", i); + // The == and != operators are provided + // Note that they work even for inline functions. + if (funclist[i]==dg) { msg = "Found equal delegate"; }; + // operator ! can be used to test for an empty delegate + // You can also use the .empty() member function. + if (!funclist[i]) { + printf("Delegate is empty\n"); + } else { + // Invocation generates optimal assembly code. + funclist[i](i, msg); + }; + } + return 0; +} + diff --git a/src/_micro-api/libraries/fastdelegate/library.properties b/src/_micro-api/libraries/fastdelegate/library.properties new file mode 100644 index 0000000..ae297cf --- /dev/null +++ b/src/_micro-api/libraries/fastdelegate/library.properties @@ -0,0 +1,8 @@ +name=fastdelegate=1.0.0 +author=Don Clugston, +maintainer=Don Clugston +sentence=fastdelegate +paragraph= +category=Uncategorized +url=https://www.codeproject.com/articles/7150/member-function-pointers-and-the-fastest-possible +architectures=* \ No newline at end of file diff --git a/src/_micro-api/libraries/fastdelegate/src/FastDelegate.h b/src/_micro-api/libraries/fastdelegate/src/FastDelegate.h new file mode 100644 index 0000000..d17ec35 --- /dev/null +++ b/src/_micro-api/libraries/fastdelegate/src/FastDelegate.h @@ -0,0 +1,2296 @@ +// FastDelegate.h +// Efficient delegates in C++ that generate only two lines of asm code! +// Documentation is found at http://www.codeproject.com/cpp/FastDelegate.asp +// +// - Don Clugston, Mar 2004. +// Major contributions were made by Jody Hagins. +// History: +// 24-Apr-04 1.0 * Submitted to CodeProject. +// 28-Apr-04 1.1 * Prevent most unsafe uses of evil static function hack. +// * Improved syntax for horrible_cast (thanks Paul Bludov). +// * Tested on Metrowerks MWCC and Intel ICL (IA32) +// * Compiled, but not run, on Comeau C++ and Intel Itanium ICL. +// 27-Jun-04 1.2 * Now works on Borland C++ Builder 5.5 +// * Now works on /clr "managed C++" code on VC7, VC7.1 +// * Comeau C++ now compiles without warnings. +// * Prevent the virtual inheritance case from being used on +// VC6 and earlier, which generate incorrect code. +// * Improved warning and error messages. Non-standard hacks +// now have compile-time checks to make them safer. +// * implicit_cast used instead of static_cast in many cases. +// * If calling a const member function, a const class pointer can be used. +// * MakeDelegate() global helper function added to simplify pass-by-value. +// * Added fastdelegate.clear() +// 16-Jul-04 1.2.1* Workaround for gcc bug (const member function pointers in templates) +// 30-Oct-04 1.3 * Support for (non-void) return values. +// * No more workarounds in client code! +// MSVC and Intel now use a clever hack invented by John Dlugosz: +// - The FASTDELEGATEDECLARE workaround is no longer necessary. +// - No more warning messages for VC6 +// * Less use of macros. Error messages should be more comprehensible. +// * Added include guards +// * Added FastDelegate::empty() to test if invocation is safe (Thanks Neville Franks). +// * Now tested on VS 2005 Express Beta, PGI C++ +// 24-Dec-04 1.4 * Added DelegateMemento, to allow collections of disparate delegates. +// * <,>,<=,>= comparison operators to allow storage in ordered containers. +// * Substantial reduction of code size, especially the 'Closure' class. +// * Standardised all the compiler-specific workarounds. +// * MFP conversion now works for CodePlay (but not yet supported in the full code). +// * Now compiles without warnings on _any_ supported compiler, including BCC 5.5.1 +// * New syntax: FastDelegate< int (char *, double) >. +// 14-Feb-05 1.4.1* Now treats =0 as equivalent to .clear(), ==0 as equivalent to .empty(). (Thanks elfric). +// * Now tested on Intel ICL for AMD64, VS2005 Beta for AMD64 and Itanium. +// 30-Mar-05 1.5 * Safebool idiom: "if (dg)" is now equivalent to "if (!dg.empty())" +// * Fully supported by CodePlay VectorC +// * Bugfix for Metrowerks: empty() was buggy because a valid MFP can be 0 on MWCC! +// * More optimal assignment,== and != operators for static function pointers. + +#ifndef FASTDELEGATE_H +#define FASTDELEGATE_H + +#if defined(ARDUINO) && ARDUINO >= 100 +#include "Arduino.h" +#else +#include "WProgram.h" +#endif + +//#include // to allow <,> comparisons + +//////////////////////////////////////////////////////////////////////////////// +// Configuration options +// +//////////////////////////////////////////////////////////////////////////////// + +// Uncomment the following #define for optimally-sized delegates. +// In this case, the generated asm code is almost identical to the code you'd get +// if the compiler had native support for delegates. +// It will not work on systems where sizeof(dataptr) < sizeof(codeptr). +// Thus, it will not work for DOS compilers using the medium model. +// It will also probably fail on some DSP systems. +#define FASTDELEGATE_USESTATICFUNCTIONHACK + +// Uncomment the next line to allow function declarator syntax. +// It is automatically enabled for those compilers where it is known to work. +//#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + +//////////////////////////////////////////////////////////////////////////////// +// Compiler identification for workarounds +// +//////////////////////////////////////////////////////////////////////////////// + +// Compiler identification. It's not easy to identify Visual C++ because +// many vendors fraudulently define Microsoft's identifiers. +#if defined(_MSC_VER) && !defined(__MWERKS__) && !defined(__VECTOR_C) && !defined(__ICL) && !defined(__BORLANDC__) +#define FASTDLGT_ISMSVC + +#if (_MSC_VER <1300) // Many workarounds are required for VC6. +#define FASTDLGT_VC6 +#pragma warning(disable:4786) // disable this ridiculous warning +#endif + +#endif + +// Does the compiler uses Microsoft's member function pointer structure? +// If so, it needs special treatment. +// Metrowerks CodeWarrior, Intel, and CodePlay fraudulently define Microsoft's +// identifier, _MSC_VER. We need to filter Metrowerks out. +#if defined(_MSC_VER) && !defined(__MWERKS__) +#define FASTDLGT_MICROSOFT_MFP + +#if !defined(__VECTOR_C) +// CodePlay doesn't have the __single/multi/virtual_inheritance keywords +#define FASTDLGT_HASINHERITANCE_KEYWORDS +#endif +#endif + +// Does it allow function declarator syntax? The following compilers are known to work: +#if defined(FASTDLGT_ISMSVC) && (_MSC_VER >=1310) // VC 7.1 +#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX +#endif + +// Gcc(2.95+), and versions of Digital Mars, Intel and Comeau in common use. +#if defined (__DMC__) || defined(__GNUC__) || defined(__ICL) || defined(__COMO__) +#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX +#endif + +// It works on Metrowerks MWCC 3.2.2. From boost.Config it should work on earlier ones too. +#if defined (__MWERKS__) +#define FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX +#endif + +#ifdef __GNUC__ // Workaround GCC bug #8271 +// At present, GCC doesn't recognize constness of MFPs in templates +#define FASTDELEGATE_GCC_BUG_8271 +#endif + + + +//////////////////////////////////////////////////////////////////////////////// +// General tricks used in this code +// +// (a) Error messages are generated by typdefing an array of negative size to +// generate compile-time errors. +// (b) Warning messages on MSVC are generated by declaring unused variables, and +// enabling the "variable XXX is never used" warning. +// (c) Unions are used in a few compiler-specific cases to perform illegal casts. +// (d) For Microsoft and Intel, when adjusting the 'this' pointer, it's cast to +// (char *) first to ensure that the correct number of *bytes* are added. +// +//////////////////////////////////////////////////////////////////////////////// +// Helper templates +// +//////////////////////////////////////////////////////////////////////////////// + + +namespace fastdelegate { + namespace detail { // we'll hide the implementation details in a nested namespace. + + // implicit_cast< > + // I believe this was originally going to be in the C++ standard but + // was left out by accident. It's even milder than static_cast. + // I use it instead of static_cast<> to emphasize that I'm not doing + // anything nasty. + // Usage is identical to static_cast<> + template + inline OutputClass implicit_cast(InputClass input) { + return input; + } + + // horrible_cast< > + // This is truly evil. It completely subverts C++'s type system, allowing you + // to cast from any class to any other class. Technically, using a union + // to perform the cast is undefined behaviour (even in C). But we can see if + // it is OK by checking that the union is the same size as each of its members. + // horrible_cast<> should only be used for compiler-specific workarounds. + // Usage is identical to reinterpret_cast<>. + + // This union is declared outside the horrible_cast because BCC 5.5.1 + // can't inline a function with a nested class, and gives a warning. + template + union horrible_union { + OutputClass out; + InputClass in; + }; + + template + inline OutputClass horrible_cast(const InputClass input) { + horrible_union u; + // Cause a compile-time error if in, out and u are not the same size. + // If the compile fails here, it means the compiler has peculiar + // unions which would prevent the cast from working. + typedef int ERROR_CantUseHorrible_cast[sizeof(InputClass) == sizeof(u) + && sizeof(InputClass) == sizeof(OutputClass) ? 1 : -1]; + u.in = input; + return u.out; + } + + //////////////////////////////////////////////////////////////////////////////// + // Workarounds + // + //////////////////////////////////////////////////////////////////////////////// + + // Backwards compatibility: This macro used to be necessary in the virtual inheritance + // case for Intel and Microsoft. Now it just forward-declares the class. +#define FASTDELEGATEDECLARE(CLASSNAME) class CLASSNAME; + + // Prevent use of the static function hack with the DOS medium model. +#ifdef __MEDIUM__ +#undef FASTDELEGATE_USESTATICFUNCTIONHACK +#endif + + // DefaultVoid - a workaround for 'void' templates in VC6. + // + // (1) VC6 and earlier do not allow 'void' as a default template argument. + // (2) They also doesn't allow you to return 'void' from a function. + // + // Workaround for (1): Declare a dummy type 'DefaultVoid' which we use + // when we'd like to use 'void'. We convert it into 'void' and back + // using the templates DefaultVoidToVoid<> and VoidToDefaultVoid<>. + // Workaround for (2): On VC6, the code for calling a void function is + // identical to the code for calling a non-void function in which the + // return value is never used, provided the return value is returned + // in the EAX register, rather than on the stack. + // This is true for most fundamental types such as int, enum, void *. + // Const void * is the safest option since it doesn't participate + // in any automatic conversions. But on a 16-bit compiler it might + // cause extra code to be generated, so we disable it for all compilers + // except for VC6 (and VC5). +#ifdef FASTDLGT_VC6 + // VC6 workaround + typedef const void * DefaultVoid; +#else + // On any other compiler, just use a normal void. + typedef void DefaultVoid; +#endif + + // Translate from 'DefaultVoid' to 'void'. + // Everything else is unchanged + template + struct DefaultVoidToVoid { typedef T type; }; + + template <> + struct DefaultVoidToVoid { typedef void type; }; + + // Translate from 'void' into 'DefaultVoid' + // Everything else is unchanged + template + struct VoidToDefaultVoid { typedef T type; }; + + template <> + struct VoidToDefaultVoid { typedef DefaultVoid type; }; + + + + //////////////////////////////////////////////////////////////////////////////// + // Fast Delegates, part 1: + // + // Conversion of member function pointer to a standard form + // + //////////////////////////////////////////////////////////////////////////////// + + // GenericClass is a fake class, ONLY used to provide a type. + // It is vitally important that it is never defined, so that the compiler doesn't + // think it can optimize the invocation. For example, Borland generates simpler + // code if it knows the class only uses single inheritance. + + // Compilers using Microsoft's structure need to be treated as a special case. +#ifdef FASTDLGT_MICROSOFT_MFP + +#ifdef FASTDLGT_HASINHERITANCE_KEYWORDS + // For Microsoft and Intel, we want to ensure that it's the most efficient type of MFP + // (4 bytes), even when the /vmg option is used. Declaring an empty class + // would give 16 byte pointers in this case.... + class __single_inheritance GenericClass; +#endif + // ...but for Codeplay, an empty class *always* gives 4 byte pointers. + // If compiled with the /clr option ("managed C++"), the JIT compiler thinks + // it needs to load GenericClass before it can call any of its functions, + // (compiles OK but crashes at runtime!), so we need to declare an + // empty class to make it happy. + // Codeplay and VC4 can't cope with the unknown_inheritance case either. + class GenericClass {}; +#else + class GenericClass; +#endif + + // The size of a single inheritance member function pointer. + const int SINGLE_MEMFUNCPTR_SIZE = sizeof(void (GenericClass::*)()); + + // SimplifyMemFunc< >::Convert() + // + // A template function that converts an arbitrary member function pointer into the + // simplest possible form of member function pointer, using a supplied 'this' pointer. + // According to the standard, this can be done legally with reinterpret_cast<>. + // For (non-standard) compilers which use member function pointers which vary in size + // depending on the class, we need to use knowledge of the internal structure of a + // member function pointer, as used by the compiler. Template specialization is used + // to distinguish between the sizes. Because some compilers don't support partial + // template specialisation, I use full specialisation of a wrapper struct. + + // general case -- don't know how to convert it. Force a compile failure + template + struct SimplifyMemFunc { + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + // Unsupported member function type -- force a compile failure. + // (it's illegal to have a array with negative size). + typedef char ERROR_Unsupported_member_function_pointer_on_this_compiler[N - 100]; + return 0; + } + }; + + // For compilers where all member func ptrs are the same size, everything goes here. + // For non-standard compilers, only single_inheritance classes go here. + template <> + struct SimplifyMemFunc { + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { +#if defined __DMC__ + // Digital Mars doesn't allow you to cast between abitrary PMF's, + // even though the standard says you can. The 32-bit compiler lets you + // static_cast through an int, but the DOS compiler doesn't. + bound_func = horrible_cast(function_to_bind); +#else + bound_func = reinterpret_cast(function_to_bind); +#endif + return reinterpret_cast(pthis); + } + }; + + //////////////////////////////////////////////////////////////////////////////// + // Fast Delegates, part 1b: + // + // Workarounds for Microsoft and Intel + // + //////////////////////////////////////////////////////////////////////////////// + + + // Compilers with member function pointers which violate the standard (MSVC, Intel, Codeplay), + // need to be treated as a special case. +#ifdef FASTDLGT_MICROSOFT_MFP + + // We use unions to perform horrible_casts. I would like to use #pragma pack(push, 1) + // at the start of each function for extra safety, but VC6 seems to ICE + // intermittently if you do this inside a template. + + // __multiple_inheritance classes go here + // Nasty hack for Microsoft and Intel (IA32 and Itanium) + template<> + struct SimplifyMemFunc< SINGLE_MEMFUNCPTR_SIZE + sizeof(int) > { + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + // We need to use a horrible_cast to do this conversion. + // In MSVC, a multiple inheritance member pointer is internally defined as: + union { + XFuncType func; + struct { + GenericMemFuncType funcaddress; // points to the actual member function + int delta; // #BYTES to be added to the 'this' pointer + }s; + } u; + // Check that the horrible_cast will work + typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind) == sizeof(u.s) ? 1 : -1]; + u.func = function_to_bind; + bound_func = u.s.funcaddress; + return reinterpret_cast(reinterpret_cast(pthis) + u.s.delta); + } + }; + + // virtual inheritance is a real nuisance. It's inefficient and complicated. + // On MSVC and Intel, there isn't enough information in the pointer itself to + // enable conversion to a closure pointer. Earlier versions of this code didn't + // work for all cases, and generated a compile-time error instead. + // But a very clever hack invented by John M. Dlugosz solves this problem. + // My code is somewhat different to his: I have no asm code, and I make no + // assumptions about the calling convention that is used. + + // In VC++ and ICL, a virtual_inheritance member pointer + // is internally defined as: + struct MicrosoftVirtualMFP { + void (GenericClass::*codeptr)(); // points to the actual member function + int delta; // #bytes to be added to the 'this' pointer + int vtable_index; // or 0 if no virtual inheritance + }; + // The CRUCIAL feature of Microsoft/Intel MFPs which we exploit is that the + // m_codeptr member is *always* called, regardless of the values of the other + // members. (This is *not* true for other compilers, eg GCC, which obtain the + // function address from the vtable if a virtual function is being called). + // Dlugosz's trick is to make the codeptr point to a probe function which + // returns the 'this' pointer that was used. + + // Define a generic class that uses virtual inheritance. + // It has a trival member function that returns the value of the 'this' pointer. + struct GenericVirtualClass : virtual public GenericClass + { + typedef GenericVirtualClass * (GenericVirtualClass::*ProbePtrType)(); + GenericVirtualClass * GetThis() { return this; } + }; + + // __virtual_inheritance classes go here + template <> + struct SimplifyMemFunc + { + + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + union { + XFuncType func; + GenericClass* (X::*ProbeFunc)(); + MicrosoftVirtualMFP s; + } u; + u.func = function_to_bind; + bound_func = reinterpret_cast(u.s.codeptr); + union { + GenericVirtualClass::ProbePtrType virtfunc; + MicrosoftVirtualMFP s; + } u2; + // Check that the horrible_cast<>s will work + typedef int ERROR_CantUsehorrible_cast[sizeof(function_to_bind) == sizeof(u.s) + && sizeof(function_to_bind) == sizeof(u.ProbeFunc) + && sizeof(u2.virtfunc) == sizeof(u2.s) ? 1 : -1]; + // Unfortunately, taking the address of a MF prevents it from being inlined, so + // this next line can't be completely optimised away by the compiler. + u2.virtfunc = &GenericVirtualClass::GetThis; + u.s.codeptr = u2.s.codeptr; + return (pthis->*u.ProbeFunc)(); + } + }; + +#if (_MSC_VER <1300) + + // Nasty hack for Microsoft Visual C++ 6.0 + // unknown_inheritance classes go here + // There is a compiler bug in MSVC6 which generates incorrect code in this case!! + template <> + struct SimplifyMemFunc + { + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + // There is an apalling but obscure compiler bug in MSVC6 and earlier: + // vtable_index and 'vtordisp' are always set to 0 in the + // unknown_inheritance case! + // This means that an incorrect function could be called!!! + // Compiling with the /vmg option leads to potentially incorrect code. + // This is probably the reason that the IDE has a user interface for specifying + // the /vmg option, but it is disabled - you can only specify /vmg on + // the command line. In VC1.5 and earlier, the compiler would ICE if it ever + // encountered this situation. + // It is OK to use the /vmg option if /vmm or /vms is specified. + + // Fortunately, the wrong function is only called in very obscure cases. + // It only occurs when a derived class overrides a virtual function declared + // in a virtual base class, and the member function + // points to the *Derived* version of that function. The problem can be + // completely averted in 100% of cases by using the *Base class* for the + // member fpointer. Ie, if you use the base class as an interface, you'll + // stay out of trouble. + // Occasionally, you might want to point directly to a derived class function + // that isn't an override of a base class. In this case, both vtable_index + // and 'vtordisp' are zero, but a virtual_inheritance pointer will be generated. + // We can generate correct code in this case. To prevent an incorrect call from + // ever being made, on MSVC6 we generate a warning, and call a function to + // make the program crash instantly. + typedef char ERROR_VC6CompilerBug[-100]; + return 0; + } + }; + + +#else + + // Nasty hack for Microsoft and Intel (IA32 and Itanium) + // unknown_inheritance classes go here + // This is probably the ugliest bit of code I've ever written. Look at the casts! + // There is a compiler bug in MSVC6 which prevents it from using this code. + template <> + struct SimplifyMemFunc + { + template + inline static GenericClass *Convert(X *pthis, XFuncType function_to_bind, + GenericMemFuncType &bound_func) { + // The member function pointer is 16 bytes long. We can't use a normal cast, but + // we can use a union to do the conversion. + union { + XFuncType func; + // In VC++ and ICL, an unknown_inheritance member pointer + // is internally defined as: + struct { + GenericMemFuncType m_funcaddress; // points to the actual member function + int delta; // #bytes to be added to the 'this' pointer + int vtordisp; // #bytes to add to 'this' to find the vtable + int vtable_index; // or 0 if no virtual inheritance + } s; + } u; + // Check that the horrible_cast will work + typedef int ERROR_CantUsehorrible_cast[sizeof(XFuncType) == sizeof(u.s) ? 1 : -1]; + u.func = function_to_bind; + bound_func = u.s.funcaddress; + int virtual_delta = 0; + if (u.s.vtable_index) { // Virtual inheritance is used + // First, get to the vtable. + // It is 'vtordisp' bytes from the start of the class. + const int * vtable = *reinterpret_cast( + reinterpret_cast(pthis) + u.s.vtordisp); + + // 'vtable_index' tells us where in the table we should be looking. + virtual_delta = u.s.vtordisp + *reinterpret_cast( + reinterpret_cast(vtable) + u.s.vtable_index); + } + // The int at 'virtual_delta' gives us the amount to add to 'this'. + // Finally we can add the three components together. Phew! + return reinterpret_cast( + reinterpret_cast(pthis) + u.s.delta + virtual_delta); + }; + }; +#endif // MSVC 7 and greater + +#endif // MS/Intel hacks + + } // namespace detail + + //////////////////////////////////////////////////////////////////////////////// + // Fast Delegates, part 2: + // + // Define the delegate storage, and cope with static functions + // + //////////////////////////////////////////////////////////////////////////////// + + // DelegateMemento -- an opaque structure which can hold an arbitary delegate. + // It knows nothing about the calling convention or number of arguments used by + // the function pointed to. + // It supplies comparison operators so that it can be stored in STL collections. + // It cannot be set to anything other than null, nor invoked directly: + // it must be converted to a specific delegate. + + // Implementation: + // There are two possible implementations: the Safe method and the Evil method. + // DelegateMemento - Safe version + // + // This implementation is standard-compliant, but a bit tricky. + // A static function pointer is stored inside the class. + // Here are the valid values: + // +-- Static pointer --+--pThis --+-- pMemFunc-+-- Meaning------+ + // | 0 | 0 | 0 | Empty | + // | !=0 |(dontcare)| Invoker | Static function| + // | 0 | !=0 | !=0* | Method call | + // +--------------------+----------+------------+----------------+ + // * For Metrowerks, this can be 0. (first virtual function in a + // single_inheritance class). + // When stored stored inside a specific delegate, the 'dontcare' entries are replaced + // with a reference to the delegate itself. This complicates the = and == operators + // for the delegate class. + + // DelegateMemento - Evil version + // + // For compilers where data pointers are at least as big as code pointers, it is + // possible to store the function pointer in the this pointer, using another + // horrible_cast. In this case the DelegateMemento implementation is simple: + // +--pThis --+-- pMemFunc-+-- Meaning---------------------+ + // | 0 | 0 | Empty | + // | !=0 | !=0* | Static function or method call| + // +----------+------------+-------------------------------+ + // * For Metrowerks, this can be 0. (first virtual function in a + // single_inheritance class). + // Note that the Sun C++ and MSVC documentation explicitly state that they + // support static_cast between void * and function pointers. + + class DelegateMemento { + protected: + // the data is protected, not private, because many + // compilers have problems with template friends. + typedef void (detail::GenericClass::*GenericMemFuncType)(); // arbitrary MFP. + detail::GenericClass *m_pthis; + GenericMemFuncType m_pFunction; + +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + typedef void(*GenericFuncPtr)(); // arbitrary code pointer + GenericFuncPtr m_pStaticFunction; +#endif + + public: +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + DelegateMemento() : m_pthis(0), m_pFunction(0), m_pStaticFunction(0) {}; + void clear() { + m_pthis = 0; m_pFunction = 0; m_pStaticFunction = 0; + } +#else + DelegateMemento() : m_pthis(0), m_pFunction(0) {}; + void clear() { m_pthis = 0; m_pFunction = 0; } +#endif + public: +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + inline bool IsEqual(const DelegateMemento &x) const { + // We have to cope with the static function pointers as a special case + if (m_pFunction != x.m_pFunction) return false; + // the static function ptrs must either both be equal, or both be 0. + if (m_pStaticFunction != x.m_pStaticFunction) return false; + if (m_pStaticFunction != 0) return m_pthis == x.m_pthis; + else return true; + } +#else // Evil Method + inline bool IsEqual(const DelegateMemento &x) const { + return m_pthis == x.m_pthis && m_pFunction == x.m_pFunction; + } +#endif + // Provide a strict weak ordering for DelegateMementos. + inline bool IsLess(const DelegateMemento &right) const { + // deal with static function pointers first +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + if (m_pStaticFunction != 0 || right.m_pStaticFunction != 0) + return m_pStaticFunction < right.m_pStaticFunction; +#endif + if (m_pthis != right.m_pthis) return m_pthis < right.m_pthis; + // There are no ordering operators for member function pointers, + // but we can fake one by comparing each byte. The resulting ordering is + // arbitrary (and compiler-dependent), but it permits storage in ordered STL containers. + return memcmp(&m_pFunction, &right.m_pFunction, sizeof(m_pFunction)) < 0; + + } + // BUGFIX (Mar 2005): + // We can't just compare m_pFunction because on Metrowerks, + // m_pFunction can be zero even if the delegate is not empty! + inline bool operator ! () const // Is it bound to anything? + { + return m_pthis == 0 && m_pFunction == 0; + } + inline bool empty() const // Is it bound to anything? + { + return m_pthis == 0 && m_pFunction == 0; + } + public: + DelegateMemento & operator = (const DelegateMemento &right) { + SetMementoFrom(right); + return *this; + } + inline bool operator <(const DelegateMemento &right) { + return IsLess(right); + } + inline bool operator >(const DelegateMemento &right) { + return right.IsLess(*this); + } + DelegateMemento(const DelegateMemento &right) : + m_pFunction(right.m_pFunction), m_pthis(right.m_pthis) +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + , m_pStaticFunction(right.m_pStaticFunction) +#endif + {} + protected: + void SetMementoFrom(const DelegateMemento &right) { + m_pFunction = right.m_pFunction; + m_pthis = right.m_pthis; +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = right.m_pStaticFunction; +#endif + } + }; + + + // ClosurePtr<> + // + // A private wrapper class that adds function signatures to DelegateMemento. + // It's the class that does most of the actual work. + // The signatures are specified by: + // GenericMemFunc: must be a type of GenericClass member function pointer. + // StaticFuncPtr: must be a type of function pointer with the same signature + // as GenericMemFunc. + // UnvoidStaticFuncPtr: is the same as StaticFuncPtr, except on VC6 + // where it never returns void (returns DefaultVoid instead). + + // An outer class, FastDelegateN<>, handles the invoking and creates the + // necessary typedefs. + // This class does everything else. + + namespace detail { + + template < class GenericMemFunc, class StaticFuncPtr, class UnvoidStaticFuncPtr> + class ClosurePtr : public DelegateMemento { + public: + // These functions are for setting the delegate to a member function. + + // Here's the clever bit: we convert an arbitrary member function into a + // standard form. XMemFunc should be a member function of class X, but I can't + // enforce that here. It needs to be enforced by the wrapper class. + template < class X, class XMemFunc > + inline void bindmemfunc(X *pthis, XMemFunc function_to_bind) { + m_pthis = SimplifyMemFunc< sizeof(function_to_bind) > + ::Convert(pthis, function_to_bind, m_pFunction); +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = 0; +#endif + } + // For const member functions, we only need a const class pointer. + // Since we know that the member function is const, it's safe to + // remove the const qualifier from the 'this' pointer with a const_cast. + // VC6 has problems if we just overload 'bindmemfunc', so we give it a different name. + template < class X, class XMemFunc> + inline void bindconstmemfunc(const X *pthis, XMemFunc function_to_bind) { + m_pthis = SimplifyMemFunc< sizeof(function_to_bind) > + ::Convert(const_cast(pthis), function_to_bind, m_pFunction); +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = 0; +#endif + } +#ifdef FASTDELEGATE_GCC_BUG_8271 // At present, GCC doesn't recognize constness of MFPs in templates + template < class X, class XMemFunc> + inline void bindmemfunc(const X *pthis, XMemFunc function_to_bind) { + bindconstmemfunc(pthis, function_to_bind); +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + m_pStaticFunction = 0; +#endif + } +#endif + // These functions are required for invoking the stored function + inline GenericClass *GetClosureThis() const { return m_pthis; } + inline GenericMemFunc GetClosureMemPtr() const { return reinterpret_cast(m_pFunction); } + + // There are a few ways of dealing with static function pointers. + // There's a standard-compliant, but tricky method. + // There's also a straightforward hack, that won't work on DOS compilers using the + // medium memory model. It's so evil that I can't recommend it, but I've + // implemented it anyway because it produces very nice asm code. + +#if !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + + // ClosurePtr<> - Safe version + // + // This implementation is standard-compliant, but a bit tricky. + // I store the function pointer inside the class, and the delegate then + // points to itself. Whenever the delegate is copied, these self-references + // must be transformed, and this complicates the = and == operators. + public: + // The next two functions are for operator ==, =, and the copy constructor. + // We may need to convert the m_pthis pointers, so that + // they remain as self-references. + template< class DerivedClass > + inline void CopyFrom(DerivedClass *pParent, const DelegateMemento &x) { + SetMementoFrom(x); + if (m_pStaticFunction != 0) { + // transform self references... + m_pthis = reinterpret_cast(pParent); + } + } + // For static functions, the 'static_function_invoker' class in the parent + // will be called. The parent then needs to call GetStaticFunction() to find out + // the actual function to invoke. + template < class DerivedClass, class ParentInvokerSig > + inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, + StaticFuncPtr function_to_bind) { + if (function_to_bind == 0) { // cope with assignment to 0 + m_pFunction = 0; + } + else { + bindmemfunc(pParent, static_function_invoker); + } + m_pStaticFunction = reinterpret_cast(function_to_bind); + } + inline UnvoidStaticFuncPtr GetStaticFunction() const { + return reinterpret_cast(m_pStaticFunction); + } +#else + + // ClosurePtr<> - Evil version + // + // For compilers where data pointers are at least as big as code pointers, it is + // possible to store the function pointer in the this pointer, using another + // horrible_cast. Invocation isn't any faster, but it saves 4 bytes, and + // speeds up comparison and assignment. If C++ provided direct language support + // for delegates, they would produce asm code that was almost identical to this. + // Note that the Sun C++ and MSVC documentation explicitly state that they + // support static_cast between void * and function pointers. + + template< class DerivedClass > + inline void CopyFrom(DerivedClass *pParent, const DelegateMemento &right) { + SetMementoFrom(right); + } + // For static functions, the 'static_function_invoker' class in the parent + // will be called. The parent then needs to call GetStaticFunction() to find out + // the actual function to invoke. + // ******** EVIL, EVIL CODE! ******* + template < class DerivedClass, class ParentInvokerSig> + inline void bindstaticfunc(DerivedClass *pParent, ParentInvokerSig static_function_invoker, + StaticFuncPtr function_to_bind) { + if (function_to_bind == 0) { // cope with assignment to 0 + m_pFunction = 0; + } + else { + // We'll be ignoring the 'this' pointer, but we need to make sure we pass + // a valid value to bindmemfunc(). + bindmemfunc(pParent, static_function_invoker); + } + + // WARNING! Evil hack. We store the function in the 'this' pointer! + // Ensure that there's a compilation failure if function pointers + // and data pointers have different sizes. + // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK. + typedef int ERROR_CantUseEvilMethod[sizeof(GenericClass *) == sizeof(function_to_bind) ? 1 : -1]; + m_pthis = horrible_cast(function_to_bind); + // MSVC, SunC++ and DMC accept the following (non-standard) code: + // m_pthis = static_cast(static_cast(function_to_bind)); + // BCC32, Comeau and DMC accept this method. MSVC7.1 needs __int64 instead of long + // m_pthis = reinterpret_cast(reinterpret_cast(function_to_bind)); + } + // ******** EVIL, EVIL CODE! ******* + // This function will be called with an invalid 'this' pointer!! + // We're just returning the 'this' pointer, converted into + // a function pointer! + inline UnvoidStaticFuncPtr GetStaticFunction() const { + // Ensure that there's a compilation failure if function pointers + // and data pointers have different sizes. + // If you get this error, you need to #undef FASTDELEGATE_USESTATICFUNCTIONHACK. + typedef int ERROR_CantUseEvilMethod[sizeof(UnvoidStaticFuncPtr) == sizeof(this) ? 1 : -1]; + return horrible_cast(this); + } +#endif // !defined(FASTDELEGATE_USESTATICFUNCTIONHACK) + + // Does the closure contain this static function? + inline bool IsEqualToStaticFuncPtr(StaticFuncPtr funcptr) { + if (funcptr == 0) return empty(); + // For the Evil method, if it doesn't actually contain a static function, this will return an arbitrary + // value that is not equal to any valid function pointer. + else return funcptr == reinterpret_cast(GetStaticFunction()); + } + }; + + + } // namespace detail + + //////////////////////////////////////////////////////////////////////////////// + // Fast Delegates, part 3: + // + // Wrapper classes to ensure type safety + // + //////////////////////////////////////////////////////////////////////////////// + + + // Once we have the member function conversion templates, it's easy to make the + // wrapper classes. So that they will work with as many compilers as possible, + // the classes are of the form + // FastDelegate3 + // They can cope with any combination of parameters. The max number of parameters + // allowed is 8, but it is trivial to increase this limit. + // Note that we need to treat const member functions seperately. + // All this class does is to enforce type safety, and invoke the delegate with + // the correct list of parameters. + + // Because of the weird rule about the class of derived member function pointers, + // you sometimes need to apply a downcast to the 'this' pointer. + // This is the reason for the use of "implicit_cast(pthis)" in the code below. + // If CDerivedClass is derived from CBaseClass, but doesn't override SimpleVirtualFunction, + // without this trick you'd need to write: + // MyDelegate(static_cast(&d), &CDerivedClass::SimpleVirtualFunction); + // but with the trick you can write + // MyDelegate(&d, &CDerivedClass::SimpleVirtualFunction); + + // RetType is the type the compiler uses in compiling the template. For VC6, + // it cannot be void. DesiredRetType is the real type which is returned from + // all of the functions. It can be void. + + // Implicit conversion to "bool" is achieved using the safe_bool idiom, + // using member data pointers (MDP). This allows "if (dg)..." syntax + // Because some compilers (eg codeplay) don't have a unique value for a zero + // MDP, an extra padding member is added to the SafeBool struct. + // Some compilers (eg VC6) won't implicitly convert from 0 to an MDP, so + // in that case the static function constructor is not made explicit; this + // allows "if (dg==0) ..." to compile. + + //N=0 + template + class FastDelegate0 { + private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType(*StaticFunctionPtr)(); + typedef RetType(*UnvoidStaticFunctionPtr)(); + typedef RetType(detail::GenericClass::*GenericMemFn)(); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; + public: + // Typedefs to aid generic programming + typedef FastDelegate0 type; + + // Construction and comparison functions + FastDelegate0() { clear(); } + FastDelegate0(const FastDelegate0 &x) { + m_Closure.CopyFrom(this, x.m_Closure); + } + void operator = (const FastDelegate0 &x) { + m_Closure.CopyFrom(this, x.m_Closure); + } + bool operator ==(const FastDelegate0 &x) const { + return m_Closure.IsEqual(x.m_Closure); + } + bool operator !=(const FastDelegate0 &x) const { + return !m_Closure.IsEqual(x.m_Closure); + } + bool operator <(const FastDelegate0 &x) const { + return m_Closure.IsLess(x.m_Closure); + } + bool operator >(const FastDelegate0 &x) const { + return x.m_Closure.IsLess(m_Closure); + } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate0(Y *pthis, DesiredRetType(X::* function_to_bind)()) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType(X::* function_to_bind)()) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Binding to const member functions. + template < class X, class Y > + FastDelegate0(const Y *pthis, DesiredRetType(X::* function_to_bind)() const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType(X::* function_to_bind)() const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate0(DesiredRetType(*function_to_bind)()) { + bind(function_to_bind); + } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType(*function_to_bind)()) { + bind(function_to_bind); + } + inline void bind(DesiredRetType(*function_to_bind)()) { + m_Closure.bindstaticfunc(this, &FastDelegate0::InvokeStaticFunction, + function_to_bind); + } + // Invoke the delegate + RetType operator() () const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(); + } + // Implicit conversion to "bool" using the safe_bool idiom + private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; + public: + operator unspecified_bool_type() const { + return empty() ? 0 : &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; + } + inline bool empty() const { + return !m_Closure; + } + void clear() { m_Closure.clear(); } + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + + private: // Invoker for static functions + RetType InvokeStaticFunction() const { + return (*(m_Closure.GetStaticFunction()))(); + } + }; + + //N=1 + template + class FastDelegate1 { + private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType(*StaticFunctionPtr)(Param1 p1); + typedef RetType(*UnvoidStaticFunctionPtr)(Param1 p1); + typedef RetType(detail::GenericClass::*GenericMemFn)(Param1 p1); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; + public: + // Typedefs to aid generic programming + typedef FastDelegate1 type; + + // Construction and comparison functions + FastDelegate1() { clear(); } + FastDelegate1(const FastDelegate1 &x) { + m_Closure.CopyFrom(this, x.m_Closure); + } + void operator = (const FastDelegate1 &x) { + m_Closure.CopyFrom(this, x.m_Closure); + } + bool operator ==(const FastDelegate1 &x) const { + return m_Closure.IsEqual(x.m_Closure); + } + bool operator !=(const FastDelegate1 &x) const { + return !m_Closure.IsEqual(x.m_Closure); + } + bool operator <(const FastDelegate1 &x) const { + return m_Closure.IsLess(x.m_Closure); + } + bool operator >(const FastDelegate1 &x) const { + return x.m_Closure.IsLess(m_Closure); + } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate1(Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Binding to const member functions. + template < class X, class Y > + FastDelegate1(const Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate1(DesiredRetType(*function_to_bind)(Param1 p1)) { + bind(function_to_bind); + } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType(*function_to_bind)(Param1 p1)) { + bind(function_to_bind); + } + inline void bind(DesiredRetType(*function_to_bind)(Param1 p1)) { + m_Closure.bindstaticfunc(this, &FastDelegate1::InvokeStaticFunction, + function_to_bind); + } + // Invoke the delegate + RetType operator() (Param1 p1) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1); + } + // Implicit conversion to "bool" using the safe_bool idiom + private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; + public: + operator unspecified_bool_type() const { + return empty() ? 0 : &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; + } + inline bool empty() const { + return !m_Closure; + } + void clear() { m_Closure.clear(); } + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + + private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1) const { + return (*(m_Closure.GetStaticFunction()))(p1); + } + }; + + //N=2 + template + class FastDelegate2 { + private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType(*StaticFunctionPtr)(Param1 p1, Param2 p2); + typedef RetType(*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2); + typedef RetType(detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; + public: + // Typedefs to aid generic programming + typedef FastDelegate2 type; + + // Construction and comparison functions + FastDelegate2() { clear(); } + FastDelegate2(const FastDelegate2 &x) { + m_Closure.CopyFrom(this, x.m_Closure); + } + void operator = (const FastDelegate2 &x) { + m_Closure.CopyFrom(this, x.m_Closure); + } + bool operator ==(const FastDelegate2 &x) const { + return m_Closure.IsEqual(x.m_Closure); + } + bool operator !=(const FastDelegate2 &x) const { + return !m_Closure.IsEqual(x.m_Closure); + } + bool operator <(const FastDelegate2 &x) const { + return m_Closure.IsLess(x.m_Closure); + } + bool operator >(const FastDelegate2 &x) const { + return x.m_Closure.IsLess(m_Closure); + } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate2(Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Binding to const member functions. + template < class X, class Y > + FastDelegate2(const Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate2(DesiredRetType(*function_to_bind)(Param1 p1, Param2 p2)) { + bind(function_to_bind); + } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType(*function_to_bind)(Param1 p1, Param2 p2)) { + bind(function_to_bind); + } + inline void bind(DesiredRetType(*function_to_bind)(Param1 p1, Param2 p2)) { + m_Closure.bindstaticfunc(this, &FastDelegate2::InvokeStaticFunction, + function_to_bind); + } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2); + } + // Implicit conversion to "bool" using the safe_bool idiom + private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; + public: + operator unspecified_bool_type() const { + return empty() ? 0 : &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; + } + inline bool empty() const { + return !m_Closure; + } + void clear() { m_Closure.clear(); } + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + + private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2); + } + }; + + //N=3 + template + class FastDelegate3 { + private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType(*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3); + typedef RetType(*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3); + typedef RetType(detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; + public: + // Typedefs to aid generic programming + typedef FastDelegate3 type; + + // Construction and comparison functions + FastDelegate3() { clear(); } + FastDelegate3(const FastDelegate3 &x) { + m_Closure.CopyFrom(this, x.m_Closure); + } + void operator = (const FastDelegate3 &x) { + m_Closure.CopyFrom(this, x.m_Closure); + } + bool operator ==(const FastDelegate3 &x) const { + return m_Closure.IsEqual(x.m_Closure); + } + bool operator !=(const FastDelegate3 &x) const { + return !m_Closure.IsEqual(x.m_Closure); + } + bool operator <(const FastDelegate3 &x) const { + return m_Closure.IsLess(x.m_Closure); + } + bool operator >(const FastDelegate3 &x) const { + return x.m_Closure.IsLess(m_Closure); + } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate3(Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Binding to const member functions. + template < class X, class Y > + FastDelegate3(const Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate3(DesiredRetType(*function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) { + bind(function_to_bind); + } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType(*function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) { + bind(function_to_bind); + } + inline void bind(DesiredRetType(*function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) { + m_Closure.bindstaticfunc(this, &FastDelegate3::InvokeStaticFunction, + function_to_bind); + } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3); + } + // Implicit conversion to "bool" using the safe_bool idiom + private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; + public: + operator unspecified_bool_type() const { + return empty() ? 0 : &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; + } + inline bool empty() const { + return !m_Closure; + } + void clear() { m_Closure.clear(); } + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + + private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3); + } + }; + + //N=4 + template + class FastDelegate4 { + private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType(*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4); + typedef RetType(*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4); + typedef RetType(detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; + public: + // Typedefs to aid generic programming + typedef FastDelegate4 type; + + // Construction and comparison functions + FastDelegate4() { clear(); } + FastDelegate4(const FastDelegate4 &x) { + m_Closure.CopyFrom(this, x.m_Closure); + } + void operator = (const FastDelegate4 &x) { + m_Closure.CopyFrom(this, x.m_Closure); + } + bool operator ==(const FastDelegate4 &x) const { + return m_Closure.IsEqual(x.m_Closure); + } + bool operator !=(const FastDelegate4 &x) const { + return !m_Closure.IsEqual(x.m_Closure); + } + bool operator <(const FastDelegate4 &x) const { + return m_Closure.IsLess(x.m_Closure); + } + bool operator >(const FastDelegate4 &x) const { + return x.m_Closure.IsLess(m_Closure); + } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate4(Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Binding to const member functions. + template < class X, class Y > + FastDelegate4(const Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate4(DesiredRetType(*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { + bind(function_to_bind); + } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType(*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { + bind(function_to_bind); + } + inline void bind(DesiredRetType(*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { + m_Closure.bindstaticfunc(this, &FastDelegate4::InvokeStaticFunction, + function_to_bind); + } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4); + } + // Implicit conversion to "bool" using the safe_bool idiom + private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; + public: + operator unspecified_bool_type() const { + return empty() ? 0 : &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; + } + inline bool empty() const { + return !m_Closure; + } + void clear() { m_Closure.clear(); } + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + + private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4); + } + }; + + //N=5 + template + class FastDelegate5 { + private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType(*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5); + typedef RetType(*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5); + typedef RetType(detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; + public: + // Typedefs to aid generic programming + typedef FastDelegate5 type; + + // Construction and comparison functions + FastDelegate5() { clear(); } + FastDelegate5(const FastDelegate5 &x) { + m_Closure.CopyFrom(this, x.m_Closure); + } + void operator = (const FastDelegate5 &x) { + m_Closure.CopyFrom(this, x.m_Closure); + } + bool operator ==(const FastDelegate5 &x) const { + return m_Closure.IsEqual(x.m_Closure); + } + bool operator !=(const FastDelegate5 &x) const { + return !m_Closure.IsEqual(x.m_Closure); + } + bool operator <(const FastDelegate5 &x) const { + return m_Closure.IsLess(x.m_Closure); + } + bool operator >(const FastDelegate5 &x) const { + return x.m_Closure.IsLess(m_Closure); + } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate5(Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Binding to const member functions. + template < class X, class Y > + FastDelegate5(const Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate5(DesiredRetType(*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { + bind(function_to_bind); + } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType(*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { + bind(function_to_bind); + } + inline void bind(DesiredRetType(*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { + m_Closure.bindstaticfunc(this, &FastDelegate5::InvokeStaticFunction, + function_to_bind); + } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5); + } + // Implicit conversion to "bool" using the safe_bool idiom + private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; + public: + operator unspecified_bool_type() const { + return empty() ? 0 : &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; + } + inline bool empty() const { + return !m_Closure; + } + void clear() { m_Closure.clear(); } + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + + private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5); + } + }; + + //N=6 + template + class FastDelegate6 { + private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType(*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6); + typedef RetType(*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6); + typedef RetType(detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; + public: + // Typedefs to aid generic programming + typedef FastDelegate6 type; + + // Construction and comparison functions + FastDelegate6() { clear(); } + FastDelegate6(const FastDelegate6 &x) { + m_Closure.CopyFrom(this, x.m_Closure); + } + void operator = (const FastDelegate6 &x) { + m_Closure.CopyFrom(this, x.m_Closure); + } + bool operator ==(const FastDelegate6 &x) const { + return m_Closure.IsEqual(x.m_Closure); + } + bool operator !=(const FastDelegate6 &x) const { + return !m_Closure.IsEqual(x.m_Closure); + } + bool operator <(const FastDelegate6 &x) const { + return m_Closure.IsLess(x.m_Closure); + } + bool operator >(const FastDelegate6 &x) const { + return x.m_Closure.IsLess(m_Closure); + } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate6(Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Binding to const member functions. + template < class X, class Y > + FastDelegate6(const Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate6(DesiredRetType(*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) { + bind(function_to_bind); + } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType(*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) { + bind(function_to_bind); + } + inline void bind(DesiredRetType(*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) { + m_Closure.bindstaticfunc(this, &FastDelegate6::InvokeStaticFunction, + function_to_bind); + } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6); + } + // Implicit conversion to "bool" using the safe_bool idiom + private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; + public: + operator unspecified_bool_type() const { + return empty() ? 0 : &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; + } + inline bool empty() const { + return !m_Closure; + } + void clear() { m_Closure.clear(); } + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + + private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6); + } + }; + + //N=7 + template + class FastDelegate7 { + private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType(*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7); + typedef RetType(*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7); + typedef RetType(detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; + public: + // Typedefs to aid generic programming + typedef FastDelegate7 type; + + // Construction and comparison functions + FastDelegate7() { clear(); } + FastDelegate7(const FastDelegate7 &x) { + m_Closure.CopyFrom(this, x.m_Closure); + } + void operator = (const FastDelegate7 &x) { + m_Closure.CopyFrom(this, x.m_Closure); + } + bool operator ==(const FastDelegate7 &x) const { + return m_Closure.IsEqual(x.m_Closure); + } + bool operator !=(const FastDelegate7 &x) const { + return !m_Closure.IsEqual(x.m_Closure); + } + bool operator <(const FastDelegate7 &x) const { + return m_Closure.IsLess(x.m_Closure); + } + bool operator >(const FastDelegate7 &x) const { + return x.m_Closure.IsLess(m_Closure); + } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate7(Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Binding to const member functions. + template < class X, class Y > + FastDelegate7(const Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate7(DesiredRetType(*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) { + bind(function_to_bind); + } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType(*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) { + bind(function_to_bind); + } + inline void bind(DesiredRetType(*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) { + m_Closure.bindstaticfunc(this, &FastDelegate7::InvokeStaticFunction, + function_to_bind); + } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7); + } + // Implicit conversion to "bool" using the safe_bool idiom + private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; + public: + operator unspecified_bool_type() const { + return empty() ? 0 : &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; + } + inline bool empty() const { + return !m_Closure; + } + void clear() { m_Closure.clear(); } + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + + private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7); + } + }; + + //N=8 + template + class FastDelegate8 { + private: + typedef typename detail::DefaultVoidToVoid::type DesiredRetType; + typedef DesiredRetType(*StaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8); + typedef RetType(*UnvoidStaticFunctionPtr)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8); + typedef RetType(detail::GenericClass::*GenericMemFn)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8); + typedef detail::ClosurePtr ClosureType; + ClosureType m_Closure; + public: + // Typedefs to aid generic programming + typedef FastDelegate8 type; + + // Construction and comparison functions + FastDelegate8() { clear(); } + FastDelegate8(const FastDelegate8 &x) { + m_Closure.CopyFrom(this, x.m_Closure); + } + void operator = (const FastDelegate8 &x) { + m_Closure.CopyFrom(this, x.m_Closure); + } + bool operator ==(const FastDelegate8 &x) const { + return m_Closure.IsEqual(x.m_Closure); + } + bool operator !=(const FastDelegate8 &x) const { + return !m_Closure.IsEqual(x.m_Closure); + } + bool operator <(const FastDelegate8 &x) const { + return m_Closure.IsLess(x.m_Closure); + } + bool operator >(const FastDelegate8 &x) const { + return x.m_Closure.IsLess(m_Closure); + } + // Binding to non-const member functions + template < class X, class Y > + FastDelegate8(Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void bind(Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) { + m_Closure.bindmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Binding to const member functions. + template < class X, class Y > + FastDelegate8(const Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + template < class X, class Y > + inline void bind(const Y *pthis, DesiredRetType(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) { + m_Closure.bindconstmemfunc(detail::implicit_cast(pthis), function_to_bind); + } + // Static functions. We convert them into a member function call. + // This constructor also provides implicit conversion + FastDelegate8(DesiredRetType(*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) { + bind(function_to_bind); + } + // for efficiency, prevent creation of a temporary + void operator = (DesiredRetType(*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) { + bind(function_to_bind); + } + inline void bind(DesiredRetType(*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) { + m_Closure.bindstaticfunc(this, &FastDelegate8::InvokeStaticFunction, + function_to_bind); + } + // Invoke the delegate + RetType operator() (Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const { + return (m_Closure.GetClosureThis()->*(m_Closure.GetClosureMemPtr()))(p1, p2, p3, p4, p5, p6, p7, p8); + } + // Implicit conversion to "bool" using the safe_bool idiom + private: + typedef struct SafeBoolStruct { + int a_data_pointer_to_this_is_0_on_buggy_compilers; + StaticFunctionPtr m_nonzero; + } UselessTypedef; + typedef StaticFunctionPtr SafeBoolStruct::*unspecified_bool_type; + public: + operator unspecified_bool_type() const { + return empty() ? 0 : &SafeBoolStruct::m_nonzero; + } + // necessary to allow ==0 to work despite the safe_bool idiom + inline bool operator==(StaticFunctionPtr funcptr) { + return m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator!=(StaticFunctionPtr funcptr) { + return !m_Closure.IsEqualToStaticFuncPtr(funcptr); + } + inline bool operator ! () const { // Is it bound to anything? + return !m_Closure; + } + inline bool empty() const { + return !m_Closure; + } + void clear() { m_Closure.clear(); } + // Conversion to and from the DelegateMemento storage class + const DelegateMemento & GetMemento() { return m_Closure; } + void SetMemento(const DelegateMemento &any) { m_Closure.CopyFrom(this, any); } + + private: // Invoker for static functions + RetType InvokeStaticFunction(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const { + return (*(m_Closure.GetStaticFunction()))(p1, p2, p3, p4, p5, p6, p7, p8); + } + }; + + + //////////////////////////////////////////////////////////////////////////////// + // Fast Delegates, part 4: + // + // FastDelegate<> class (Original author: Jody Hagins) + // Allows boost::function style syntax like: + // FastDelegate< double (int, long) > + // instead of: + // FastDelegate2< int, long, double > + // + //////////////////////////////////////////////////////////////////////////////// + +#ifdef FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + + // Declare FastDelegate as a class template. It will be specialized + // later for all number of arguments. + template + class FastDelegate; + + //N=0 + // Specialization to allow use of + // FastDelegate< R ( ) > + // instead of + // FastDelegate0 < R > + template + class FastDelegate< R() > + // Inherit from FastDelegate0 so that it can be treated just like a FastDelegate0 + : public FastDelegate0 < R > + { + public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate0 < R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R(X::* function_to_bind)()) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R(X::* function_to_bind)() const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R(*function_to_bind)()) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; + } + }; + + //N=1 + // Specialization to allow use of + // FastDelegate< R ( Param1 ) > + // instead of + // FastDelegate1 < Param1, R > + template + class FastDelegate< R(Param1) > + // Inherit from FastDelegate1 so that it can be treated just like a FastDelegate1 + : public FastDelegate1 < Param1, R > + { + public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate1 < Param1, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R(X::* function_to_bind)(Param1 p1)) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R(X::* function_to_bind)(Param1 p1) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R(*function_to_bind)(Param1 p1)) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; + } + }; + + //N=2 + // Specialization to allow use of + // FastDelegate< R ( Param1, Param2 ) > + // instead of + // FastDelegate2 < Param1, Param2, R > + template + class FastDelegate< R(Param1, Param2) > + // Inherit from FastDelegate2 so that it can be treated just like a FastDelegate2 + : public FastDelegate2 < Param1, Param2, R > + { + public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate2 < Param1, Param2, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R(X::* function_to_bind)(Param1 p1, Param2 p2)) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R(X::* function_to_bind)(Param1 p1, Param2 p2) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R(*function_to_bind)(Param1 p1, Param2 p2)) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; + } + }; + + //N=3 + // Specialization to allow use of + // FastDelegate< R ( Param1, Param2, Param3 ) > + // instead of + // FastDelegate3 < Param1, Param2, Param3, R > + template + class FastDelegate< R(Param1, Param2, Param3) > + // Inherit from FastDelegate3 so that it can be treated just like a FastDelegate3 + : public FastDelegate3 < Param1, Param2, Param3, R > + { + public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate3 < Param1, Param2, Param3, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R(*function_to_bind)(Param1 p1, Param2 p2, Param3 p3)) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; + } + }; + + //N=4 + // Specialization to allow use of + // FastDelegate< R ( Param1, Param2, Param3, Param4 ) > + // instead of + // FastDelegate4 < Param1, Param2, Param3, Param4, R > + template + class FastDelegate< R(Param1, Param2, Param3, Param4) > + // Inherit from FastDelegate4 so that it can be treated just like a FastDelegate4 + : public FastDelegate4 < Param1, Param2, Param3, Param4, R > + { + public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate4 < Param1, Param2, Param3, Param4, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R(*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; + } + }; + + //N=5 + // Specialization to allow use of + // FastDelegate< R ( Param1, Param2, Param3, Param4, Param5 ) > + // instead of + // FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > + template + class FastDelegate< R(Param1, Param2, Param3, Param4, Param5) > + // Inherit from FastDelegate5 so that it can be treated just like a FastDelegate5 + : public FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > + { + public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate5 < Param1, Param2, Param3, Param4, Param5, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R(*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; + } + }; + + //N=6 + // Specialization to allow use of + // FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6 ) > + // instead of + // FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > + template + class FastDelegate< R(Param1, Param2, Param3, Param4, Param5, Param6) > + // Inherit from FastDelegate6 so that it can be treated just like a FastDelegate6 + : public FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > + { + public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate6 < Param1, Param2, Param3, Param4, Param5, Param6, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R(*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; + } + }; + + //N=7 + // Specialization to allow use of + // FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7 ) > + // instead of + // FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > + template + class FastDelegate< R(Param1, Param2, Param3, Param4, Param5, Param6, Param7) > + // Inherit from FastDelegate7 so that it can be treated just like a FastDelegate7 + : public FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > + { + public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate7 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R(*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; + } + }; + + //N=8 + // Specialization to allow use of + // FastDelegate< R ( Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8 ) > + // instead of + // FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > + template + class FastDelegate< R(Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8) > + // Inherit from FastDelegate8 so that it can be treated just like a FastDelegate8 + : public FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > + { + public: + // Make using the base type a bit easier via typedef. + typedef FastDelegate8 < Param1, Param2, Param3, Param4, Param5, Param6, Param7, Param8, R > BaseType; + + // Allow users access to the specific type of this delegate. + typedef FastDelegate SelfType; + + // Mimic the base class constructors. + FastDelegate() : BaseType() { } + + template < class X, class Y > + FastDelegate(Y * pthis, + R(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) + : BaseType(pthis, function_to_bind) { } + + template < class X, class Y > + FastDelegate(const Y *pthis, + R(X::* function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) + : BaseType(pthis, function_to_bind) + { } + + FastDelegate(R(*function_to_bind)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) + : BaseType(function_to_bind) { } + void operator = (const BaseType &x) { + *static_cast(this) = x; + } + }; + + +#endif //FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + + //////////////////////////////////////////////////////////////////////////////// + // Fast Delegates, part 5: + // + // MakeDelegate() helper function + // + // MakeDelegate(&x, &X::func) returns a fastdelegate of the type + // necessary for calling x.func() with the correct number of arguments. + // This makes it possible to eliminate many typedefs from user code. + // + //////////////////////////////////////////////////////////////////////////////// + + // Also declare overloads of a MakeDelegate() global function to + // reduce the need for typedefs. + // We need seperate overloads for const and non-const member functions. + // Also, because of the weird rule about the class of derived member function pointers, + // implicit downcasts may need to be applied later to the 'this' pointer. + // That's why two classes (X and Y) appear in the definitions. Y must be implicitly + // castable to X. + + // Workaround for VC6. VC6 needs void return types converted into DefaultVoid. + // GCC 3.2 and later won't compile this unless it's preceded by 'typename', + // but VC6 doesn't allow 'typename' in this context. + // So, I have to use a macro. + +#ifdef FASTDLGT_VC6 +#define FASTDLGT_RETTYPE detail::VoidToDefaultVoid::type +#else +#define FASTDLGT_RETTYPE RetType +#endif + + //N=0 + template + FastDelegate0 MakeDelegate(Y* x, RetType(X::*func)()) { + return FastDelegate0(x, func); + } + + template + FastDelegate0 MakeDelegate(Y* x, RetType(X::*func)() const) { + return FastDelegate0(x, func); + } + + //N=1 + template + FastDelegate1 MakeDelegate(Y* x, RetType(X::*func)(Param1 p1)) { + return FastDelegate1(x, func); + } + + template + FastDelegate1 MakeDelegate(Y* x, RetType(X::*func)(Param1 p1) const) { + return FastDelegate1(x, func); + } + + //N=2 + template + FastDelegate2 MakeDelegate(Y* x, RetType(X::*func)(Param1 p1, Param2 p2)) { + return FastDelegate2(x, func); + } + + template + FastDelegate2 MakeDelegate(Y* x, RetType(X::*func)(Param1 p1, Param2 p2) const) { + return FastDelegate2(x, func); + } + + //N=3 + template + FastDelegate3 MakeDelegate(Y* x, RetType(X::*func)(Param1 p1, Param2 p2, Param3 p3)) { + return FastDelegate3(x, func); + } + + template + FastDelegate3 MakeDelegate(Y* x, RetType(X::*func)(Param1 p1, Param2 p2, Param3 p3) const) { + return FastDelegate3(x, func); + } + + //N=4 + template + FastDelegate4 MakeDelegate(Y* x, RetType(X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4)) { + return FastDelegate4(x, func); + } + + template + FastDelegate4 MakeDelegate(Y* x, RetType(X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4) const) { + return FastDelegate4(x, func); + } + + //N=5 + template + FastDelegate5 MakeDelegate(Y* x, RetType(X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5)) { + return FastDelegate5(x, func); + } + + template + FastDelegate5 MakeDelegate(Y* x, RetType(X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5) const) { + return FastDelegate5(x, func); + } + + //N=6 + template + FastDelegate6 MakeDelegate(Y* x, RetType(X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6)) { + return FastDelegate6(x, func); + } + + template + FastDelegate6 MakeDelegate(Y* x, RetType(X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6) const) { + return FastDelegate6(x, func); + } + + //N=7 + template + FastDelegate7 MakeDelegate(Y* x, RetType(X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7)) { + return FastDelegate7(x, func); + } + + template + FastDelegate7 MakeDelegate(Y* x, RetType(X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7) const) { + return FastDelegate7(x, func); + } + + //N=8 + template + FastDelegate8 MakeDelegate(Y* x, RetType(X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8)) { + return FastDelegate8(x, func); + } + + template + FastDelegate8 MakeDelegate(Y* x, RetType(X::*func)(Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8) const) { + return FastDelegate8(x, func); + } + + + // clean up after ourselves... +#undef FASTDLGT_RETTYPE + +} // namespace fastdelegate + +#endif // !defined(FASTDELEGATE_H) \ No newline at end of file diff --git a/src/_micro-api/libraries/fastdelegate/src/FastDelegateBind.h b/src/_micro-api/libraries/fastdelegate/src/FastDelegateBind.h new file mode 100644 index 0000000..9830ab5 --- /dev/null +++ b/src/_micro-api/libraries/fastdelegate/src/FastDelegateBind.h @@ -0,0 +1,243 @@ +// FastDelegateBind.h +// Helper file for FastDelegates. Provides bind() function, enabling +// FastDelegates to be rapidly compared to programs using boost::function and boost::bind. +// +// Documentation is found at http://www.codeproject.com/cpp/FastDelegate.asp +// +// Original author: Jody Hagins. +// Minor changes by Don Clugston. +// +// Warning: The arguments to 'bind' are ignored! No actual binding is performed. +// The behaviour is equivalent to boost::bind only when the basic placeholder +// arguments _1, _2, _3, etc are used in order. +// +// HISTORY: +// 1.4 Dec 2004. Initial release as part of FastDelegate 1.4. + + +#ifndef FASTDELEGATEBIND_H +#define FASTDELEGATEBIND_H +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +//////////////////////////////////////////////////////////////////////////////// +// FastDelegate bind() +// +// bind() helper function for boost compatibility. +// (Original author: Jody Hagins). +// +// Add another helper, so FastDelegate can be a dropin replacement +// for boost::bind (in a fair number of cases). +// Note the elipses, because boost::bind() takes place holders +// but FastDelegate does not care about them. Getting the place holder +// mechanism to work, and play well with boost is a bit tricky, so +// we do the "easy" thing... +// Assume we have the following code... +// using boost::bind; +// bind(&Foo:func, &foo, _1, _2); +// we should be able to replace the "using" with... +// using fastdelegate::bind; +// and everything should work fine... +//////////////////////////////////////////////////////////////////////////////// + +#ifdef FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + +namespace fastdelegate { + +//N=0 +template +FastDelegate< RetType ( ) > +bind( + RetType (X::*func)( ), + Y * y, + ...) +{ + return FastDelegate< RetType ( ) >(y, func); +} + +template +FastDelegate< RetType ( ) > +bind( + RetType (X::*func)( ) const, + Y * y, + ...) +{ + return FastDelegate< RetType ( ) >(y, func); +} + +//N=1 +template +FastDelegate< RetType ( Param1 p1 ) > +bind( + RetType (X::*func)( Param1 p1 ), + Y * y, + ...) +{ + return FastDelegate< RetType ( Param1 p1 ) >(y, func); +} + +template +FastDelegate< RetType ( Param1 p1 ) > +bind( + RetType (X::*func)( Param1 p1 ) const, + Y * y, + ...) +{ + return FastDelegate< RetType ( Param1 p1 ) >(y, func); +} + +//N=2 +template +FastDelegate< RetType ( Param1 p1, Param2 p2 ) > +bind( + RetType (X::*func)( Param1 p1, Param2 p2 ), + Y * y, + ...) +{ + return FastDelegate< RetType ( Param1 p1, Param2 p2 ) >(y, func); +} + +template +FastDelegate< RetType ( Param1 p1, Param2 p2 ) > +bind( + RetType (X::*func)( Param1 p1, Param2 p2 ) const, + Y * y, + ...) +{ + return FastDelegate< RetType ( Param1 p1, Param2 p2 ) >(y, func); +} + +//N=3 +template +FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3 ) > +bind( + RetType (X::*func)( Param1 p1, Param2 p2, Param3 p3 ), + Y * y, + ...) +{ + return FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3 ) >(y, func); +} + +template +FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3 ) > +bind( + RetType (X::*func)( Param1 p1, Param2 p2, Param3 p3 ) const, + Y * y, + ...) +{ + return FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3 ) >(y, func); +} + +//N=4 +template +FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) > +bind( + RetType (X::*func)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ), + Y * y, + ...) +{ + return FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) >(y, func); +} + +template +FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) > +bind( + RetType (X::*func)( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) const, + Y * y, + ...) +{ + return FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4 ) >(y, func); +} + +//N=5 +template +FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) > +bind( + RetType (X::*func)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ), + Y * y, + ...) +{ + return FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) >(y, func); +} + +template +FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) > +bind( + RetType (X::*func)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) const, + Y * y, + ...) +{ + return FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5 ) >(y, func); +} + +//N=6 +template +FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) > +bind( + RetType (X::*func)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ), + Y * y, + ...) +{ + return FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) >(y, func); +} + +template +FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) > +bind( + RetType (X::*func)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) const, + Y * y, + ...) +{ + return FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6 ) >(y, func); +} + +//N=7 +template +FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) > +bind( + RetType (X::*func)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ), + Y * y, + ...) +{ + return FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) >(y, func); +} + +template +FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) > +bind( + RetType (X::*func)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) const, + Y * y, + ...) +{ + return FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7 ) >(y, func); +} + +//N=8 +template +FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) > +bind( + RetType (X::*func)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ), + Y * y, + ...) +{ + return FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) >(y, func); +} + +template +FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) > +bind( + RetType (X::*func)( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) const, + Y * y, + ...) +{ + return FastDelegate< RetType ( Param1 p1, Param2 p2, Param3 p3, Param4 p4, Param5 p5, Param6 p6, Param7 p7, Param8 p8 ) >(y, func); +} + + +#endif //FASTDELEGATE_ALLOW_FUNCTION_TYPE_SYNTAX + +} // namespace fastdelegate + +#endif // !defined(FASTDELEGATEBIND_H) + From 0dff13f5d321915ed05a323948ecdfc3043fa618 Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Fri, 18 Aug 2017 23:42:31 +0200 Subject: [PATCH 10/40] Updated SignalDetectorClass and BitStore --- .../libraries/bitstore/library.properties | 3 +- .../libraries/bitstore/src/bitstore.h | 38 +- .../signalDecoder/src/signalDecoder.cpp | 1358 ++++++++++------- .../signalDecoder/src/signalDecoder.h | 87 +- 4 files changed, 899 insertions(+), 587 deletions(-) diff --git a/src/_micro-api/libraries/bitstore/library.properties b/src/_micro-api/libraries/bitstore/library.properties index f84e34e..7623107 100644 --- a/src/_micro-api/libraries/bitstore/library.properties +++ b/src/_micro-api/libraries/bitstore/library.properties @@ -1,5 +1,4 @@ -name=bitstore -version=1.0.0 +name=bitstoreversion=1.0.0 author=Visual Micro maintainer=Visual Micro sentence=bitstore library code diff --git a/src/_micro-api/libraries/bitstore/src/bitstore.h b/src/_micro-api/libraries/bitstore/src/bitstore.h index b31251b..780fb69 100644 --- a/src/_micro-api/libraries/bitstore/src/bitstore.h +++ b/src/_micro-api/libraries/bitstore/src/bitstore.h @@ -29,20 +29,18 @@ class BitStore BitStore(uint8_t bitlength); //~BitStore(); void addValue(char value); - unsigned char getValue(const uint16_t pos); - const uint16_t getSize(); + unsigned char getValue(uint8_t pos); + const uint8_t getSize(); //unsigned char *datastore; // Reserve 40 Bytes for our store. Should be edited to aa dynamic way unsigned char datastore[bufSize]; void reset(); - unsigned char getByte(const int8_t idx); + unsigned char getByte(uint8_t idx); uint8_t bytecount; // Number of stored bytes - uint16_t valcount; // Number of total values stored -#ifndef UNITTEST - protected: + uint8_t valcount; // Number of total values stored + protected: private: -#endif - uint8_t valuelen; // Number of bits for every value + uint8_t valuelen; // Number of bits for every value uint8_t bmask; uint8_t bcnt; const uint8_t buffsize; @@ -97,41 +95,35 @@ template void BitStore::addValue(char value) { if (bytecount >=buffsize ) return; // Out of Buffer - if (bcnt==7 &&valcount > 0) - { - bytecount++; - datastore[bytecount] = 0; - } - //store[bytecount]=datastore[bytecount] | (value<= 0) // Soalnge nicht 8 Bit gepeichert wurden, erhöhen wir den counter zum verschieben + if ((bcnt-valuelen) >= 0) // Soalnge nicht 8 Bit geppeichert wurden, erhöhen wir den counter zum verschieben { bcnt=bcnt-valuelen; //+valuelen } else { bcnt=7; + bytecount++; + datastore[bytecount]=0; } } template -const uint16_t BitStore::getSize() +const uint8_t BitStore::getSize() { - return valcount-1; + return valcount; } - - template -unsigned char BitStore::getValue(const uint16_t pos) +unsigned char BitStore::getValue(uint8_t pos) { if ((pos*valuelen/8) >=buffsize ) return -1; // Out of Buffer @@ -146,7 +138,7 @@ unsigned char BitStore::getValue(const uint16_t pos) } template -unsigned char BitStore::getByte(const int8_t idx) +unsigned char BitStore::getByte(uint8_t idx) { if (idx >= buffsize) return -1; // Out of buffer range return (datastore[idx]); diff --git a/src/_micro-api/libraries/signalDecoder/src/signalDecoder.cpp b/src/_micro-api/libraries/signalDecoder/src/signalDecoder.cpp index 2a7e8b2..85b4a8e 100644 --- a/src/_micro-api/libraries/signalDecoder/src/signalDecoder.cpp +++ b/src/_micro-api/libraries/signalDecoder/src/signalDecoder.cpp @@ -2,8 +2,7 @@ * Pattern Decoder Library V3 * Library to decode radio signals based on patternd detection * 2014-2015 N.Butzek, S.Butzek -* 2015 S.Butzek -* 2016 S.Butzek +* 2015-2017 S.Butzek * This library contains classes to perform decoding of digital signals * typical for home automation. The focus for the moment is on different sensors @@ -30,26 +29,46 @@ */ #include "signalDecoder.h" -#define ETHERNET_PRINT; -#include void SignalDetectorClass::bufferMove(const uint8_t start) { - static uint8_t len_single_entry = sizeof(*message); + m_truncated = false; + //DBG_PRINTLN(""); + if (start > messageLen - 1 || start == 0) { + //DBG_PRINT(__FUNCTION__); DBG_PRINT(" start oor "); DBG_PRINT(start); DBG_PRINT(" "); DBG_PRINT(messageLen); + } + else if (message.moveLeft(start)) + { + m_truncated = true; + //DBG_PRINT(__FUNCTION__); DBG_PRINT(" -> "); DBG_PRINT(start); DBG_PRINT(" "); DBG_PRINT(messageLen); + //DBG_PRINT(" "); DBG_PRINT(message.bytecount); + messageLen = messageLen - start; - if (start > messageLen-1) return; + } + else { + //DBG_PRINT(__FUNCTION__); DBG_PRINT(" unsup "); DBG_PRINT(start); + //printOut(); + } - messageLen = messageLen - start; // Berechnung der neuen Nachrichtenlänge nach dem Löschen - memmove(message, message + start, len_single_entry*messageLen); } inline void SignalDetectorClass::addData(const uint8_t value) { - message[messageLen] = value; - messageLen++; + //message += value; + /*if (message.valcount >= 254) + { + DBG_PRINTLN(""); DBG_PRINT(__FUNCTION__); DBG_PRINT(" msglen: "); DBG_PRINT(messageLen); + }*/ + if (message.addValue(value)) + { + messageLen++; + } + else { + MSG_PRINTLN(F("addData overflow!!")); + } } inline void SignalDetectorClass::addPattern() @@ -58,7 +77,7 @@ inline void SignalDetectorClass::addPattern() pattern_pos++; } -inline void SignalDetectorClass::updPattern( const uint8_t ppos) +inline void SignalDetectorClass::updPattern(const uint8_t ppos) { pattern[ppos] = (long(pattern[ppos]) + *first) / 2; // Moving average } @@ -66,177 +85,83 @@ inline void SignalDetectorClass::updPattern( const uint8_t ppos) inline void SignalDetectorClass::doDetect() { - - bool valid=true; - valid = (messageLen==0 || (*first ^ *last) < 0); // true if a and b have opposite signs - valid &= (messageLen == maxMsgSize) ? false : true; - -// if (messageLen == 0) pattern_pos = patternLen = 0; - //if (messageLen == 0) valid = true; + //printOut(); + bool valid; + valid = (messageLen == 0 || last == NULL || (*first ^ *last) < 0); // true if a and b have opposite signs + valid &= (messageLen == maxMsgSize) ? false : true; + valid &= (*first > -maxPulse); // if low maxPulse detected, start processMessage() - if (!valid) - { - // Try output - - m_overflow = (messageLen == maxMsgSize) ? true : false; - processMessage(); - - } else if (messageLen == minMessageLen) { - state = detecting; // Set state to detecting, because we have more than minMessageLen data gathered, so this is no noise + // if (messageLen == 0) pattern_pos = patternLen = 0; + //if (messageLen == 0) valid = true; + if (!valid) { + // Try output + processMessage(); + if (messageLen < minMessageLen) { + MsMoveCount = 3; } - int8_t fidx = findpatt(*first); - if (fidx >= 0) { - // Upd pattern + } + else if (messageLen == minMessageLen) { + state = detecting; // Set state to detecting, because we have more than minMessageLen data gathered, so this is no noise + rssiValue = _rssiCallback(); + } - updPattern(fidx); - } - else { - // Add pattern + int8_t fidx = findpatt(*first); + if (fidx >= 0) { + // Upd pattern + + updPattern(fidx); + } + else { - for (int16_t i = messageLen - 1; (patternLen == maxNumPattern) && (i >= 0); --i) + // Add pattern + if (patternLen == maxNumPattern) + { + calcHisto(); + if (histo[patternLen] > 2) processMessage(); + for (int16_t i = messageLen - 1; i > 0; --i) { - if (message[i] == pattern_pos) // Finde den letzten Verweis im Array auf den Index der gleich überschrieben wird + if (message[i] == pattern_pos) // Finde den letzten Verweis im Array auf den Index der gleich ueberschrieben wird { - i++; // i um eins erhöhen, damit zukünftigen Berechnungen darauf aufbauen können + i++; // i um eins erhoehen, damit zukuenftigen Berechnungen darauf aufbauen koennen bufferMove(i); + break; } } - fidx = pattern_pos; - addPattern(); - - if (pattern_pos == maxNumPattern) - { - pattern_pos = 0; // Wenn der Positions Index am Ende angelegt ist, gehts wieder bei 0 los und wir überschreiben alte pattern - patternLen = maxNumPattern; - mcDetected = false; // When changing a pattern, we need to redetect a manchester signal and we are not in a buffer full mode scenario - - } - if (pattern_pos > patternLen) patternLen = pattern_pos; - - } - - // Add data to buffer - addData(fidx); - - -#if DEBUGDETECT>3 - Serial.print("Pulse: "); Serial.print(*first); Serial.print(", "); Serial.print(*last); - Serial.print(", TOL: "); Serial.print(tol); Serial.print(", Found: "); Serial.print(fidx); - Serial.print(", Vld: "); Serial.print(valid); - Serial.print(", pattPos: "); Serial.print(pattern_pos); - Serial.print(", mLen: "); Serial.println(messageLen); -#endif - return; - - bool add_new_pattern = true; - - if (0 <= fidx) { - - //gefunden - if (messageLen > 0 && message[messageLen - 1] == fidx) { // Der Fall darf eigentlich nicht vorkommen da hier Valid = 0 sein muss - add_new_pattern = true; - valid = false; - } else { - add_new_pattern = false; - //addData(fidx); - updPattern(fidx); - } - } - else { - // Prüfen ob wir noch Muster in den Puffer aufnehmen können oder ob wir Muster überschreiben würden - calcHisto(); - if (patternLen == maxNumPattern && histo[pattern_pos] > 1) - { - valid = false; - add_new_pattern = true; - } } - if (!valid) { - //Serial.println("not valid, processing"); + fidx = pattern_pos; + addPattern(); - //success = true; - processMessage(); - // reset(); // GGF hier nicht ausführen. - pattern_pos = 0; - //doDetectwoSync(); //Sichert den aktuellen Puls nach dem Reset, da wir ihn ggf. noch benötigen - - //return; - } - /*else if (!valid) { - reset(); - success = false; - pattern_pos = 0; - }*/ - else if (valid && messageLen >= minMessageLen) { - state = detecting; // Set state to detecting, because we have more than minMessageLen data gathered, so this is no noise - } - /*else { - if (messageLen>=minMessageLen){ - // Annahme, wir haben eine Nachricht empfangen, jetzt kommt rauschen, welches nicht zum Muster passt - //printOut(); - //processMessage(); - //reset();pattern_pos=0; - } - */ - if (add_new_pattern) + if (pattern_pos == maxNumPattern) { - // Löscht alle Einträge in dem Nachrichten Array die durch das hinzugügen eines neuen Pattern überschrieben werden - // Array wird sozusagen nach links geschoben - - for (uint8_t i = messageLen - 1; (i >= 0); --i) - { - if (message[i] == pattern_pos) // Finde den letzten Verweis im Array auf den Index der gleich überschrieben wird - { - i++; // i um eins erhöhen, damit zukünftigen Berechnungen darauf aufbauen können - bufferMove(i); - messageLen++; //Move messagelen pointer one forward to avoid overwrite - break; - } - } - pattern[pattern_pos] = *first; //Store pulse in pattern array - message[messageLen] = pattern_pos; -#if DEBUGDETECT>3 - Serial.print(F(", pattPos: ")); Serial.print(pattern_pos); -#endif // DEBUGDETECT - //*(message+messageLen) = patternLen; //Index des letzten Elements in die Nachricht schreiben - - messageLen++; - pattern_pos++; + pattern_pos = 0; // Wenn der Positions Index am Ende angelegt ist, gehts wieder bei 0 los und wir ueberschreiben alte pattern + patternLen = maxNumPattern; + mcDetected = false; // When changing a pattern, we need to redetect a manchester signal and we are not in a buffer full mode scenario - //printOut(); - if (pattern_pos == maxNumPattern) - { - pattern_pos = 0; // Wenn der Positions Index am Ende angelegt ist, gehts wieder bei 0 los und wir überschreiben alte pattern - patternLen = maxNumPattern; - } + } + if (pattern_pos > patternLen) patternLen = pattern_pos; - mcDetected = false; // When changing a pattern, we need to redetect a manchester signal and we are not in a buffer full mode scenario + } - /* - if (pattern_pos==maxNumPattern) - { - pattern_pos=0; // Wenn der Positions Index am Ende angelegt ist, gehts wieder bei 0 los und wir überschreiben alte pattern - patternLen=maxNumPattern; - } else { + // Add data to buffer + addData(fidx); - patternLen++; - } - */ - /* - DEBUG_BEGIN(2) - printOut(); - DEBUG_END - */ - } -#if DEBUGDETECT>3 - Serial.println(); -#endif // DEBUGDETECT +#if DEBUGDETECT > 3 + DBG_PRINT("Pulse: "); DBG_PRINT(*first); + DBG_PRINT(", "); DBG_PRINT(*last); + DBG_PRINT(", TOL: "); DBG_PRINT(tol); DBG_PRINT(", fidx: "); DBG_PRINT(fidx); + DBG_PRINT(", Vld: "); DBG_PRINT(valid); + DBG_PRINT(", pattPos: "); DBG_PRINT(pattern_pos); + DBG_PRINT(", mLen: "); DBG_PRINT(messageLen); + DBG_PRINT(", BC:"); DBG_PRINT(message.bytecount); + DBG_PRINT(", vcnt:"); DBG_PRINT(message.valcount); + DBG_PRINTLN(" "); +#endif } @@ -244,14 +169,10 @@ inline void SignalDetectorClass::doDetect() bool SignalDetectorClass::decode(const int * pulse) { success = false; - - //int temp; - //*first = *last; - //*last = *pulse; if (messageLen > 0) last = &pattern[message[messageLen - 1]]; *first = *pulse; - + doDetect(); return success; } @@ -259,14 +180,16 @@ bool SignalDetectorClass::decode(const int * pulse) void SignalDetectorClass::compress_pattern() { - calcHisto(); - for (uint8_t idx = 0; idx> 15) + continue; const int16_t tol = int((abs(pattern[idx2])*tolFact) + (abs(pattern[idx2])*tolFact) / 2); if (inTol(pattern[idx2], pattern[idx], tol)) // Pattern are very equal, so we can combine them { @@ -275,31 +198,28 @@ void SignalDetectorClass::compress_pattern() { if (message[i] == idx2) { - message[i] = idx; + message.changeValue(i, idx); } } #if DEBUGDETECT>2 - Serial.print("compr: "); Serial.print(idx2); Serial.print("->"); Serial.print(idx); Serial.print(";"); - Serial.print(histo[idx2]); Serial.print("*"); Serial.print(pattern[idx2]); - Serial.print("->"); - Serial.print(histo[idx]); Serial.print("*"); Serial.print(pattern[idx]); + DBG_PRINT("compr: "); DBG_PRINT(idx2); DBG_PRINT("->"); DBG_PRINT(idx); DBG_PRINT(";"); + DBG_PRINT(histo[idx2]); DBG_PRINT("*"); DBG_PRINT(pattern[idx2]); + DBG_PRINT("->"); + DBG_PRINT(histo[idx]); DBG_PRINT("*"); DBG_PRINT(pattern[idx]); + #endif // DEBUGDETECT int sum = histo[idx] + histo[idx2]; - if (sum == 0) - pattern[idx] = (long(pattern[idx]) * histo[idx] / sum) + (pattern[idx2] * histo[idx2] / sum); - else - pattern[idx] = (long(pattern[idx]) + pattern[idx2]) / 2; - //pattern[idx][0] = (pattern[idx][0]*float(histo[idx]/ sum))+(pattern[idx2][0]*float(histo[idx2]/ sum)); // Store the average of both pattern, may better to calculate the number of stored pattern in message - //pattern[idx][0] = (pattern[idx][0]+pattern[idx2][0])/2; - pattern[idx2] = 0; + pattern[idx] = ((long(pattern[idx]) * histo[idx]) + (pattern[idx2] * histo[idx2])) / sum; + histo[idx] += histo[idx2]; + pattern[idx2] = histo[idx2] = 0; #if DEBUGDETECT>2 - Serial.print(" idx:"); Serial.print(pattern[idx]); - Serial.print(" idx2:"); Serial.print(pattern[idx2]); - Serial.println(";"); + DBG_PRINT(" idx:"); DBG_PRINT(pattern[idx]); + DBG_PRINT(" idx2:"); DBG_PRINT(pattern[idx2]); + DBG_PRINTLN(";"); #endif // DEBUGDETECT } @@ -309,12 +229,16 @@ void SignalDetectorClass::compress_pattern() void SignalDetectorClass::processMessage() { - + yield(); + if (mcDetected == true || messageLen >= minMessageLen) { success = false; + m_overflow = (messageLen == maxMsgSize) ? true : false; + #if DEBUGDETECT >= 1 - Serial.println("Message received:"); + DBG_PRINTLN("Message received:"); #endif + compress_pattern(); calcHisto(); getClock(); @@ -324,17 +248,17 @@ void SignalDetectorClass::processMessage() printOut(); #endif - if (MSenabled && state == syncfound && messageLen >= minMessageLen)// Messages mit clock / Sync Verhältnis prüfen + if (MSenabled && state == syncfound && messageLen >= minMessageLen)// Messages mit clock / Sync Verhaeltnis pruefen { #if DEBUGDECODE >0 - Serial.print(" MS check: "); + MSG_PRINT(" MS check: "); //printOut(); #endif // Setup of some protocol identifiers, should be retrieved via fhem in future - mend = mstart + 2; // GGf. kann man die Mindestlänge von x Signalen vorspringen + mend = mstart + 2; // GGf. kann man die Mindestlaenge von x Signalen vorspringen bool m_endfound = false; //uint8_t repeat; @@ -354,49 +278,118 @@ void SignalDetectorClass::processMessage() #if DEBUGDECODE > 1 - Serial.print("Index: "); - Serial.print(" MStart: "); Serial.print(mstart); - Serial.print(" SYNC: "); Serial.print(sync); - Serial.print(", CP: "); Serial.print(clock); - Serial.print(" - MEFound: "); Serial.println(m_endfound); - Serial.print(" - MEnd: "); Serial.println(mend); + DBG_PRINT("Index: "); + DBG_PRINT(" MStart: "); DBG_PRINT(mstart); + DBG_PRINT(" SYNC: "); DBG_PRINT(sync); + DBG_PRINT(", CP: "); DBG_PRINT(clock); + DBG_PRINT(" - MEFound: "); DBG_PRINTLN(m_endfound); + DBG_PRINT(" - MEnd: "); DBG_PRINTLN(mend); #endif // DEBUGDECODE - if ((m_endfound && (mend - mstart) >= minMessageLen) || (!m_endfound && messageLen < (maxMsgSize)))//(!m_endfound && messageLen >= minMessageLen)) // Check if message Length is long enough + if ((m_endfound && (mend - mstart) >= minMessageLen) || (!m_endfound && messageLen < (maxMsgSize))) //(!m_endfound && messageLen >= minMessageLen)) // Check if message Length is long enough { #ifdef DEBUGDECODE - Serial.println("Filter Match: ");; + MSG_PRINTLN("Filter Match: ");; #endif - preamble = ""; - postamble = ""; + //preamble = ""; + //postamble = ""; /* Output raw message Data */ - preamble.concat(MSG_START); - //preamble.concat('\n'); - preamble.concat("MS"); // Message Index - //preamble.concat(int(pattern[sync][0]/(float)pattern[clock][0])); - preamble.concat(SERIAL_DELIMITER); // Message Index - for (uint8_t idx = 0; idx < patternLen; idx++) - { - if (histo[idx] == 0) continue; - preamble.concat('P'); preamble.concat(idx); preamble.concat("="); preamble.concat(pattern[idx]); preamble.concat(SERIAL_DELIMITER); // Patternidx=Value + if (MredEnabled) { + int patternInt; + uint8_t patternLow; + uint8_t patternIdx; + + MSG_PRINT(MSG_START); MSG_PRINT("Ms"); MSG_PRINT(SERIAL_DELIMITER); + for (uint8_t idx = 0; idx < patternLen; idx++) + { + if (pattern[idx] == 0 || histo[idx] == 0) continue; + patternIdx = idx; + patternInt = pattern[idx]; + + if (patternInt < 0) { + patternIdx = idx | B10100000; // Bit5 = 1 (Vorzeichen negativ) + patternInt = -patternInt; + } + else { + patternIdx = idx | B10000000; // Bit5 = 0 (Vorzeichen positiv) + } + + patternLow = lowByte(patternInt); + if (bitRead(patternLow, 7) == 0) { + bitSet(patternLow, 7); + } + else { + bitSet(patternIdx, 4); // wenn bei patternLow Bit7 gesetzt ist, dann bei patternIdx Bit4 = 1 + } + MSG_WRITE(patternIdx); + MSG_WRITE(patternLow); + MSG_WRITE(highByte(patternInt) | B10000000); + MSG_PRINT(SERIAL_DELIMITER); + } + + uint8_t n; + + if ((mend & 1) == 1) { // ungerade + MSG_PRINT("D"); + } + else { + MSG_PRINT("d"); + } + if ((mstart & 1) == 1) { // ungerade + mstart--; + (message.getByte(mstart / 2, &n) & 15) | 128; // high nibble = 8 als Kennzeichen für ungeraden mstart + MSG_WRITE(n); + mstart += 2; + } + for (uint8_t i = mstart; i <= mend; i = i + 2) { + message.getByte(i / 2, &n); + MSG_WRITE(n); + } + + MSG_PRINT(SERIAL_DELIMITER); + MSG_PRINT("C"); MSG_PRINT(clock, HEX); MSG_PRINT(SERIAL_DELIMITER); + MSG_PRINT("S"); MSG_PRINT(sync, HEX); MSG_PRINT(SERIAL_DELIMITER); + MSG_PRINT("R"); MSG_PRINT(rssiValue, HEX); MSG_PRINT(SERIAL_DELIMITER); + } + else { + MSG_PRINT(MSG_START); MSG_PRINT("MS"); MSG_PRINT(SERIAL_DELIMITER); + for (uint8_t idx = 0; idx < patternLen; idx++) + { + if (pattern[idx] == 0 || histo[idx] == 0) continue; + MSG_PRINT('P'); MSG_PRINT(idx); MSG_PRINT('='); MSG_PRINT(pattern[idx]); MSG_PRINT(SERIAL_DELIMITER); + } + MSG_PRINT("D="); + + for (uint8_t i = mstart; i <= mend; ++i) + { + MSG_PRINT(message[i]); + } + MSG_PRINT(SERIAL_DELIMITER); + MSG_PRINT("CP="); MSG_PRINT(clock); MSG_PRINT(SERIAL_DELIMITER); // ClockPulse + MSG_PRINT("SP="); MSG_PRINT(sync); MSG_PRINT(SERIAL_DELIMITER); // SyncPulse + MSG_PRINT("R="); MSG_PRINT(rssiValue); MSG_PRINT(SERIAL_DELIMITER); // Signal Level (RSSI) } - preamble.concat("D="); - postamble.concat(SERIAL_DELIMITER); - postamble.concat("CP="); postamble.concat(clock); postamble.concat(SERIAL_DELIMITER); // ClockPulse - postamble.concat("SP="); postamble.concat(sync); postamble.concat(SERIAL_DELIMITER); // SyncPuöse if (m_overflow) { - postamble.concat("O"); - postamble.concat(SERIAL_DELIMITER); + MSG_PRINT("O"); MSG_PRINT(SERIAL_DELIMITER); + } + m_truncated = false; + + if ((messageLen - mend) >= minMessageLen && MsMoveCount > 0) { + //MSG_PRINT(F("MS move. messageLen ")); MSG_PRINT(messageLen); MSG_PRINT(" "); MSG_PRINTLN(MsMoveCount) + MsMoveCount--; + bufferMove(mend + 1); + //MSG_PRINT(F("MS move. messageLen ")); MSG_PRINTLN(messageLen); + mstart = 0; + MSG_PRINT("m"); MSG_PRINT(MsMoveCount); MSG_PRINT(SERIAL_DELIMITER); } - postamble.concat(MSG_END); - postamble.concat('\n'); - printMsgRaw(mstart, mend, &preamble, &postamble); - success = true; + MSG_PRINT(MSG_END); + MSG_PRINT("\n"); + success = true; #ifdef mp_crc const int8_t crco = printMsgRaw(mstart, mend, &preamble, &postamble); @@ -419,126 +412,124 @@ void SignalDetectorClass::processMessage() } - else if (m_endfound == false && mstart > 1 && mend + 1 >= maxMsgSize) // Start found, but no end. We remove everything bevore start and hope to find the end later + else if (m_endfound == false && mstart > 0 && mend + 1 >= maxMsgSize) // Start found, but no end. We remove everything bevore start and hope to find the end later { - //Serial.print("copy"); + //MSG_PRINT("copy"); #ifdef DEBUGDECODE - Serial.print(" move msg ");; + DBG_PRINT(" move msg ");; #endif bufferMove(mstart); - m_truncated = true; // Flag that we truncated the message array and want to receiver some more data + mstart = 0; + //m_truncated = true; // Flag that we truncated the message array and want to receiver some more data + } + else if (m_endfound && mend < maxMsgSize) { // Start and end found, but end is not at end of buffer, so we remove only what was checked +#ifdef DEBUGDECODE + DBG_PRINT(" move msg ");; +#endif + bufferMove(mend + 1); + mstart = 0; + //m_truncated = true; // Flag that we truncated the message array and want to receiver some more data + success = true; // don't process other message types } else { #ifdef DEBUGDECODE - Serial.println(" Buffer overflow, flushing message array"); + MSG_PRINTLN(" Buffer overflow, flushing message array"); #endif - //Serial.print(MSG_START); - //Serial.print("Buffer overflow while processing signal"); - //Serial.print(MSG_END); + //MSG_PRINT(MSG_START); + //MSG_PRINT("Buffer overflow while processing signal"); + //MSG_PRINT(MSG_END); reset(); // Our Messagebuffer is not big enough, no chance to get complete Message + success = true; // don't process other message types } } if (success == false && (MUenabled || MCenabled)) { #if DEBUGDECODE >0 - Serial.print(" MU/MC check: "); + DBG_PRINT(" check:"); //printOut(); #endif -// Message has a clock puls, but no sync. Try to decode this - - preamble = ""; - postamble = ""; + // Message has a clock puls, but no sync. Try to decode this + //preamble = ""; + //postamble = ""; - //String preamble; - - preamble.concat(MSG_START); if (MCenabled) { + //DBG_PRINT(" mc: "); + static ManchesterpatternDecoder mcdecoder(this); // Init Manchester Decoder class if (mcDetected == false) { mcdecoder.reset(); - mcdecoder.setMinBitLen(17); // Todo: allow modification via command + mcdecoder.setMinBitLen(mcMinBitLen); } #if DEBUGDETECT>3 - Serial.print("vcnt: "); Serial.print(mcdecoder.ManchesterBits.valcount); -#endif; + MSG_PRINT("vcnt: "); MSG_PRINT(mcdecoder.ManchesterBits.valcount); +#endif if ((mcDetected || mcdecoder.isManchester()) && mcdecoder.doDecode()) // Check if valid manchester pattern and try to decode { #if DEBUGDECODE > 1 - Serial.print(" MC found: "); + MSG_PRINT(" MC found: "); #endif // DEBUGDECODE - String mcbitmsg; - //Serial.println("MC"); - mcbitmsg = "D="; - mcdecoder.getMessageHexStr(&mcbitmsg); - //Serial.println("f"); - - - preamble.concat("MC"); - preamble.concat(SERIAL_DELIMITER); - mcdecoder.getMessagePulseStr(&preamble); - - postamble.concat(SERIAL_DELIMITER); - mcdecoder.getMessageClockStr(&postamble); - mcdecoder.getMessageLenStr(&postamble); - - - postamble.concat(MSG_END); - postamble.concat('\n'); - - //messageLen=messageLen-mend; // Berechnung der neuen Nachrichtenlänge nach dem Löschen - //memmove(message,message+mend,sizeof(*message)*(messageLen+1)); - //m_truncated=true; // Flag that we truncated the message array and want to receiver some more data - - //preamble = String(MSG_START)+String("MC")+String(SERIAL_DELIMITER)+preamble; - //printMsgRaw(0,messageLen,&preamble,&postamble); - - //preamble.concat("MC"); ; preamble.concat(SERIAL_DELIMITER); // Message Index - - // Output Manchester Bits -#ifdef DEBUGDECODE - Serial.println(" "); -#endif - - printMsgStr(&preamble, &mcbitmsg, &postamble); - mcDetected = false; - success = true; - #if DEBUGDECODE == 1 - preamble = "MC"; - preamble.concat(SERIAL_DELIMITER); + MSG_PRINT(MSG_START); + MSG_PRINT("MC"); + MSG_PRINT(SERIAL_DELIMITER); for (uint8_t idx = 0; idx < patternLen; idx++) { if (histo[idx] == 0) continue; + MSG_PRINT('P'); MSG_PRINT(idx); MSG_PRINT('='); MSG_PRINT(pattern[idx]); MSG_PRINT(SERIAL_DELIMITER); + } + MSG_PRINT("D="); + - preamble.concat("P"); preamble.concat(idx); preamble.concat("="); preamble.concat(pattern[idx]); preamble.concat(SERIAL_DELIMITER); // Patternidx=Value + mend = min(mend, messageLen); // Workaround if mend=255 + for (uint8_t i = mstart; i <= mend; ++i) + { + MSG_PRINT(message[i]); } - preamble.concat("D="); + MSG_PRINT(SERIAL_DELIMITER); - //String postamble; - postamble = String(SERIAL_DELIMITER); - postamble.concat("CP="); postamble.concat(clock); postamble.concat(SERIAL_DELIMITER); // ClockPulse, (not valid for manchester) if (m_overflow) { - postamble.concat("O"); - postamble.concat(SERIAL_DELIMITER); + MSG_PRINT("O"); + MSG_PRINT(SERIAL_DELIMITER); } + MSG_PRINTLN(MSG_END); +#endif + MSG_PRINT(MSG_START); + MSG_PRINT("MC"); + MSG_PRINT(SERIAL_DELIMITER); + MSG_PRINT("LL="); MSG_PRINT(pattern[mcdecoder.longlow]); MSG_PRINT(SERIAL_DELIMITER); + MSG_PRINT("LH="); MSG_PRINT(pattern[mcdecoder.longhigh]); MSG_PRINT(SERIAL_DELIMITER); + MSG_PRINT("SL="); MSG_PRINT(pattern[mcdecoder.shortlow]); MSG_PRINT(SERIAL_DELIMITER); + MSG_PRINT("SH="); MSG_PRINT(pattern[mcdecoder.shorthigh]); MSG_PRINT(SERIAL_DELIMITER); + MSG_PRINT("D="); mcdecoder.printMessageHexStr(); + MSG_PRINT(SERIAL_DELIMITER); + MSG_PRINT("C="); MSG_PRINT(mcdecoder.clock); MSG_PRINT(SERIAL_DELIMITER); + MSG_PRINT("L="); MSG_PRINT(mcdecoder.ManchesterBits.valcount); MSG_PRINT(SERIAL_DELIMITER); + MSG_PRINT("R="); MSG_PRINT(rssiValue); MSG_PRINT(SERIAL_DELIMITER); // Signal Level (RSSI) + MSG_PRINT(MSG_END); + MSG_PRINT("\n"); - postamble.concat(MSG_END); - postamble.concat('\n'); - - printMsgRaw(0, messageLen, &preamble, &postamble); +#ifdef DEBUGDECODE + DBG_PRINTLN(""); #endif + // printMsgStr(&preamble, &mcbitmsg, &postamble); + mcDetected = false; + success = true; + + + } else if (mcDetected == true && m_truncated == true) { + success = true; // Prevents MU Processing } @@ -546,53 +537,104 @@ void SignalDetectorClass::processMessage() if (MUenabled && state == clockfound && success == false && messageLen >= minMessageLen) { #if DEBUGDECODE > 1 - Serial.print(" MU found: "); + DBG_PRINT(" MU found: "); #endif // DEBUGDECODE - //preamble = String(MSG_START)+String("MU")+String(SERIAL_DELIMITER)+preamble; + if (MredEnabled) { + int patternInt; + uint8_t patternLow; + uint8_t patternIdx; + + MSG_PRINT(MSG_START); MSG_PRINT("Mu"); MSG_PRINT(SERIAL_DELIMITER); + for (uint8_t idx = 0; idx < patternLen; idx++) + { + if (pattern[idx] == 0 || histo[idx] == 0) continue; + patternIdx = idx; + patternInt = pattern[idx]; + + if (patternInt < 0) { + patternIdx = idx | B10100000; // Bit5 = 1 (Vorzeichen negativ) + patternInt = -patternInt; + } + else { + patternIdx = idx | B10000000; // Bit5 = 0 (Vorzeichen positiv) + } + + patternLow = lowByte(patternInt); + if (bitRead(patternLow, 7) == 0) { + bitSet(patternLow, 7); + } + else { + bitSet(patternIdx, 4); // wenn bei patternLow Bit7 gesetzt ist, dann bei patternIdx Bit4 = 1 + } + MSG_WRITE(patternIdx); + MSG_WRITE(patternLow); + MSG_WRITE(highByte(patternInt) | B10000000); + MSG_PRINT(SERIAL_DELIMITER); + } - preamble.concat("MU"); - preamble.concat(SERIAL_DELIMITER); + uint8_t n; - for (uint8_t idx = 0; idx < patternLen; idx++) - { - if (histo[idx] == 0) continue; + if ((messageLen & 1) == 1) { // ungerade + MSG_PRINT("D"); + } + else { + MSG_PRINT("d"); + } + + for (uint8_t i = 0; i < messageLen; i = i + 2) { + message.getByte(i / 2, &n); + MSG_WRITE(n); + } + + MSG_PRINT(SERIAL_DELIMITER); + MSG_PRINT("C"); MSG_PRINT(clock, HEX); MSG_PRINT(SERIAL_DELIMITER); + MSG_PRINT("R"); MSG_PRINT(rssiValue, HEX); MSG_PRINT(SERIAL_DELIMITER); + } + else { - preamble.concat("P"); preamble.concat(idx); preamble.concat("="); preamble.concat(pattern[idx]); preamble.concat(SERIAL_DELIMITER); // Patternidx=Value + MSG_PRINT(MSG_START); MSG_PRINT("MU"); MSG_PRINT(SERIAL_DELIMITER); + + for (uint8_t idx = 0; idx < patternLen; idx++) + { + if (pattern[idx] == 0 || histo[idx] == 0) continue; + MSG_PRINT("P"); MSG_PRINT(idx); MSG_PRINT("="); MSG_PRINT(pattern[idx]); MSG_PRINT(SERIAL_DELIMITER); // Patternidx=Value + } + MSG_PRINT("D="); + for (uint8_t i = 0; i < messageLen; ++i) + { + MSG_PRINT(message[i]); + } + //String postamble; + MSG_PRINT(SERIAL_DELIMITER); + MSG_PRINT("CP="); MSG_PRINT(clock); MSG_PRINT(SERIAL_DELIMITER); // ClockPulse, (not valid for manchester) + MSG_PRINT("R="); MSG_PRINT(rssiValue); MSG_PRINT(SERIAL_DELIMITER); // Signal Level (RSSI) } - preamble.concat("D="); - //String postamble; - postamble.concat(SERIAL_DELIMITER); - postamble.concat("CP="); postamble.concat(clock); postamble.concat(SERIAL_DELIMITER); // ClockPulse, (not valid for manchester) if (m_overflow) { - postamble.concat("O"); - postamble.concat(SERIAL_DELIMITER); + MSG_PRINT("O"); MSG_PRINT(SERIAL_DELIMITER); } - postamble.concat(MSG_END); - postamble.concat('\n'); + MSG_PRINT(MSG_END); MSG_PRINT("\n"); - printMsgRaw(0, messageLen - 1, &preamble, &postamble); m_truncated = false; success = true; } - - } - - if (success == false) + + if (success == false) { #if DEBUGDETECT >= 1 - Serial.println("nothing to to"); + DBG_PRINTLN("nothing to to"); #endif } } - if (!m_truncated) + if (!m_truncated) // Todo: Eventuell auf vollen Puffer prüfen { reset(); } - //Serial.println("process finished"); + + //MSG_PRINTLN("process finished"); } @@ -605,11 +647,12 @@ void SignalDetectorClass::reset() messageLen = 0; patternLen = 0; pattern_pos = 0; - bitcnt = 0; + message.reset(); + // bitcnt = 0; state = searching; clock = sync = -1; for (uint8_t i = 0; i SyncFact: "); Serial.print(pattern[sync] / (float)pattern[clock]); - Serial.print(", Clock: "); Serial.print(pattern[clock]); - Serial.print(", Tol: "); Serial.print(tol); - Serial.print(", PattLen: "); Serial.print(patternLen); Serial.print(" "); - Serial.print(", Pulse: "); Serial.print(*first); Serial.print(", "); Serial.print(*last); - Serial.print(", mStart: "); Serial.print(mstart); - Serial.print(", MCD: "); Serial.print(mcDetected); - - - Serial.println(); Serial.print("Signal: "); + DBG_PRINTLN(""); + if (sync > -1) { + DBG_PRINT("Sync: "); DBG_PRINT(pattern[sync]); + DBG_PRINT(" -> SyncFact: "); DBG_PRINT(pattern[sync] / (float)pattern[clock]); + DBG_PRINT(","); + } + DBG_PRINT(" Clock: "); DBG_PRINT(pattern[clock]); + DBG_PRINT(", Tol: "); DBG_PRINT(tol); + DBG_PRINT(", PattLen: "); DBG_PRINT(patternLen); DBG_PRINT(" ("); DBG_PRINT(pattern_pos); DBG_PRINT(")"); + DBG_PRINT(", Pulse: "); DBG_PRINT(*first); DBG_PRINT(", "); DBG_PRINT(*last); + DBG_PRINT(", mStart: "); DBG_PRINT(mstart); + DBG_PRINT(", MCD: "); DBG_PRINT(mcDetected, DEC); + DBG_PRINT(", mtrunc: "); DBG_PRINT(m_truncated, DEC); + + + DBG_PRINTLN(); DBG_PRINT("Signal: "); uint8_t idx; for (idx = 0; idx pattern[idx][x] - //if (!inTol(seq[x],pattern[idx][x-1])) // Skip this iteration, if seq[x] <> pattern[idx][x] + if ((val ^ pattern[idx]) >> 15) + continue; + if (pattern[idx] != 0 && inTol(val, pattern[idx], tol)) // Skip this iteration, if seq[x] <> pattern[idx][x] + //if (!inTol(seq[x],pattern[idx][x-1])) // Skip this iteration, if seq[x] <> pattern[idx][x] { return idx; } @@ -688,7 +741,7 @@ int8_t SignalDetectorClass::findpatt(const int val) /* bool SignalDecoderClass::validSequence(const int * a, const int * b) { - return ((*a ^ *b) < 0); // true if a and b have opposite signs +return ((*a ^ *b) < 0); // true if a and b have opposite signs } */ @@ -698,27 +751,39 @@ void SignalDetectorClass::calcHisto(const uint8_t startpos, uint8_t endpos) { histo[i] = 0; } - - yield(); - if (endpos == 0) endpos = messageLen; - for (uint8_t i = startpos; i> 4]++; + histo[bval & B00001111]++; } + if (endpos % 2 == 1) + histo[bval & B00001111]--; + + } bool SignalDetectorClass::getClock() { - // Durchsuchen aller Musterpulse und prüft ob darin eine clock vorhanden ist + // Durchsuchen aller Musterpulse und prueft ob darin eine clock vorhanden ist #if DEBUGDETECT > 3 - Serial.println(" -- Searching Clock in signal -- "); + MSG_PRINTLN(" -- Searching Clock in signal -- "); #endif int tstclock = -1; + state = searching; clock = -1; // Workaround for sync detection bug. - for (uint8_t i = 0; i 3276) continue; // Annahme Werte <0 / >3276 sind keine Clockpulse if (tstclock == -1 && (pattern[i] >= 0) && (histo[i] > messageLen*0.17)) @@ -733,7 +798,7 @@ bool SignalDetectorClass::getClock() } - // Check Anzahl der Clockpulse von der Nachrichtenlänge + // Check Anzahl der Clockpulse von der Nachrichtenlaenge //if ((tstclock == 3276) || (maxcnt < (messageLen /7*2))) return false; if (tstclock == -1) return false; @@ -747,20 +812,18 @@ bool SignalDetectorClass::getClock() bool SignalDetectorClass::getSync() { - // Durchsuchen aller Musterpulse und prüft ob darin ein Sync Faktor enthalten ist. Anschließend wird verifiziert ob dieser Syncpuls auch im Signal nacheinander übertragen wurde + // Durchsuchen aller Musterpulse und prueft ob darin ein Sync Faktor enthalten ist. Anschließend wird verifiziert ob dieser Syncpuls auch im Signal nacheinander uebertragen wurde // #if DEBUGDETECT > 3 - Serial.println(" -- Searching Sync -- "); + DBG_PRINTLN(" -- Searching Sync -- "); #endif if (state == clockfound) // we need a clock to find this type of sync { - yield(); - // clock wurde bereits durch getclock bestimmt. - for (int8_t p = patternLen - 1; p >= 0; --p) // Schleife für langen Syncpuls + for (int8_t p = patternLen - 1; p >= 0; --p) // Schleife fuer langen Syncpuls { - //if (pattern[p] > 0 || (abs(pattern[p]) > syncMaxMicros && abs(pattern[p])/pattern[clock] > syncMaxFact)) continue; // Werte >0 oder länger maxfact sind keine Sync Pulse + //if (pattern[p] > 0 || (abs(pattern[p]) > syncMaxMicros && abs(pattern[p])/pattern[clock] > syncMaxFact)) continue; // Werte >0 oder laenger maxfact sind keine Sync Pulse //if (pattern[p] == -1*maxPulse) continue; // Werte >0 sind keine Sync Pulse //if (!validSequence(&pattern[clock],&pattern[p])) continue; /* @@ -778,20 +841,23 @@ bool SignalDetectorClass::getSync() (syncabs > syncMinFact*pattern[clock]) && // (syncabs < maxPulse) && // (validSequence(&pattern[clock],&pattern[p])) && - (histo[p] < 8) && (histo[p] > 1) + (histo[p] < messageLen*0.08) && (histo[p] > 1) + //(histo[p] < 8) && (histo[p] > 1) + //(syncMinFact*pattern[clock] <= syncabs) ) { + yield(); //if ((syncMinFact* (pattern[clock]) <= -1*pattern[p])) {//n>9 => langer Syncpulse (als 10*int16 darstellbar - // Prüfe ob Sync und Clock valide sein können + // Pruefe ob Sync und Clock valide sein koennen // if (histo[p] > 6) continue; // Maximal 6 Sync Pulse Todo: 6 Durch Formel relativ zu messageLen ersetzen - // Prüfen ob der gefundene Sync auch als message [clock, p] vorkommt + // Pruefen ob der gefundene Sync auch als message [clock, p] vorkommt uint8_t c = 0; - //while (c < messageLen-1 && message[c+1] != p && message[c] != clock) // Todo: Abstand zum Ende berechnen, da wir eine mindest Nachrichtenlänge nach dem sync erwarten, brauchen wir nicht bis zum Ende suchen. + //while (c < messageLen-1 && message[c+1] != p && message[c] != clock) // Todo: Abstand zum Ende berechnen, da wir eine mindest Nachrichtenlaenge nach dem sync erwarten, brauchen wir nicht bis zum Ende suchen. - while (c < messageLen - 1) // Todo: Abstand zum Ende berechnen, da wir eine mindest Nachrichtenlänge nach dem sync erwarten, brauchen wir nicht bis zum Ende suchen. + while (c < messageLen - 1) // Todo: Abstand zum Ende berechnen, da wir eine mindest Nachrichtenlaenge nach dem sync erwarten, brauchen wir nicht bis zum Ende suchen. { if (message[c + 1] == p && message[c] == clock) break; c++; @@ -806,11 +872,11 @@ bool SignalDetectorClass::getSync() #ifdef DEBUGDECODE //debug - Serial.println(); - Serial.print("PD sync: "); - Serial.print(pattern[clock]); Serial.print(", "); Serial.print(pattern[p]); - Serial.print(", TOL: "); Serial.print(tol); - Serial.print(", sFACT: "); Serial.println(pattern[sync] / (float)pattern[clock]); + DBG_PRINTLN(); + DBG_PRINT("PD sync: "); + DBG_PRINT(pattern[clock]); DBG_PRINT(", "); DBG_PRINT(pattern[p]); + DBG_PRINT(", TOL: "); DBG_PRINT(tol); + DBG_PRINT(", sFACT: "); DBG_PRINTLN(pattern[sync] / (float)pattern[clock]); #endif return true; } @@ -838,13 +904,13 @@ int8_t SignalDetectorClass::printMsgRaw(uint8_t m_start, const uint8_t m_end, co for (; m_start <= m_end; m_start++) { //msg + =message[m_start]; - //Serial.print((100*message[m_start])+(10*message[m_start])+message[m_start]); + //MSG_PRINT((100*message[m_start])+(10*message[m_start])+message[m_start]); MSG_PRINT(message[m_start]); #ifndef ARDUSIM //crcv = _crc_ibutton_update(crcv, message[m_start]); #endif } - //Serial.print(msg); + //MSG_PRINT(msg); MSG_PRINT(*postamble); return crcv; //printMsgStr(preamble,&msg,postamble);} @@ -889,15 +955,19 @@ ManchesterpatternDecoder::~ManchesterpatternDecoder() */ void ManchesterpatternDecoder::reset() { - - longlow = -1; - longhigh = -1; - shortlow = -1; +#ifdef DEBUGDECODE + DBG_PRINT("mcrst:"); +#endif + longlow = -1; + longhigh = -1; + shortlow = -1; shorthigh = -1; - - bool mc_start_found = false; - bool mc_sync = false; - minbitlen = 20; // Set defaults + + mc_start_found = false; + mc_sync = false; + + clock = 0; + //minbitlen = 20; // Set defaults ManchesterBits.reset(); } /** @brief (Sets internal minbitlen to new value) @@ -935,34 +1005,59 @@ const bool ManchesterpatternDecoder::isShort(const uint8_t pulse_idx) */ void ManchesterpatternDecoder::getMessageHexStr(String *message) { - char hexStr[] = "00" ; // Not really needed + char hexStr[] = "00"; // Not really needed - message->reserve((ManchesterBits.valcount /4)+2); + message->reserve((ManchesterBits.valcount / 4) + 2); if (!message) return; uint8_t idx; // Bytes are stored from left to right in our buffer. We reverse them for better readability - for ( idx = 0; idx <= ManchesterBits.bytecount-1; ++idx) { - //Serial.print(getMCByte(idx),HEX); + for (idx = 0; idx <= ManchesterBits.bytecount - 1; ++idx) { + //MSG_PRINT(getMCByte(idx),HEX); //sprintf(hexStr, "%02X",reverseByte(ManchesterBits->>getByte(idx))); - //Serial.print("."); + //MSG_PRINT("."); sprintf(hexStr, "%02X", getMCByte(idx)); message->concat(hexStr); - //Serial.print(hexStr); + //MSG_PRINT(hexStr); } - + sprintf(hexStr, "%01X", getMCByte(idx) >> 4 & 0xf); message->concat(hexStr); - if (ManchesterBits.valcount % 8 > 4) + if (ManchesterBits.valcount % 8 > 4 || ManchesterBits.valcount % 8 == 0) { sprintf(hexStr, "%01X", getMCByte(idx) & 0xF); message->concat(hexStr); } - //Serial.println(); + //MSG_PRINTLN(); + +} + +/** @brief (Converts decoded manchester bits in a provided string as hex) +* +* () +*/ +void ManchesterpatternDecoder::printMessageHexStr() +{ + char hexStr[] = "00"; // Not really needed + + uint8_t idx; + // Bytes are stored from left to right in our buffer. We reverse them for better readability + for (idx = 0; idx <= ManchesterBits.bytecount - 1; ++idx) { + sprintf(hexStr, "%02X", getMCByte(idx)); + MSG_PRINT(hexStr); + } + sprintf(hexStr, "%01X", getMCByte(idx) >> 4 & 0xf); + MSG_PRINT(hexStr); + if (ManchesterBits.valcount % 8 > 4 || ManchesterBits.valcount % 8 == 0) + { + sprintf(hexStr, "%01X", getMCByte(idx) & 0xF); + MSG_PRINT(hexStr); + } } + /** @brief (one liner) * * (documentation goes here) @@ -979,6 +1074,18 @@ void ManchesterpatternDecoder::getMessagePulseStr(String* str) str->concat("SH="); str->concat(pdec->pattern[shorthigh]); str->concat(SERIAL_DELIMITER); } +/** @brief (one liner) +* +* (documentation goes here) +*/ +void ManchesterpatternDecoder::printMessagePulseStr() +{ + MSG_PRINT("LL="); MSG_PRINT(pdec->pattern[longlow]); MSG_PRINT(SERIAL_DELIMITER); + MSG_PRINT("LH="); MSG_PRINT(pdec->pattern[longhigh]); MSG_PRINT(SERIAL_DELIMITER); + MSG_PRINT("SL="); MSG_PRINT(pdec->pattern[shortlow]); MSG_PRINT(SERIAL_DELIMITER); + MSG_PRINT("SH="); MSG_PRINT(pdec->pattern[shorthigh]); MSG_PRINT(SERIAL_DELIMITER); +} + /** @brief (one liner) * * (documentation goes here) @@ -1006,7 +1113,9 @@ void ManchesterpatternDecoder::getMessageLenStr(String* str) unsigned char ManchesterpatternDecoder::getMCByte(const uint8_t idx) { - return ManchesterBits.getByte(idx); + unsigned char c; + ManchesterBits.getByte(idx, &c); + return c; } @@ -1018,158 +1127,247 @@ unsigned char ManchesterpatternDecoder::getMCByte(const uint8_t idx) { */ const bool ManchesterpatternDecoder::doDecode() { - //Serial.print("bitcnt:");Serial.println(bitcnt); + //MSG_PRINT("bitcnt:");MSG_PRINTLN(bitcnt); uint8_t i = 0; pdec->m_truncated = false; -// bool mc_start_found = false; -// bool mc_sync = false; - pdec->mstart = 0; + // bool mc_start_found = false; + // bool mc_sync = false; + pdec->mstart = 0; // Todo: pruefen ob start aus isManchester uebernommen werden kann #ifdef DEBUGDECODE - Serial.print("mlen:"); - Serial.print(pdec->messageLen); - Serial.print(":mstart: "); - Serial.print(pdec->mstart); + DBG_PRINT("mlen:"); + DBG_PRINT(pdec->messageLen); + DBG_PRINT(":mstart: "); + DBG_PRINT(pdec->mstart); + DBG_PRINTLN(""); + #endif - char lastbit; + // char lastbit; + bool ht = false; + bool hasbit = false; while (i < pdec->messageLen) { - // Start vom MC Signal suchen if (mc_start_found == false && (isLong(pdec->message[i]) || isShort(pdec->message[i]))) { pdec->mstart = i; mc_start_found = true; + mc_sync = true; + + // lookup for first long + int pulseCnt = 0; + bool preamble = false; + for (uint8_t l = i; lmessageLen; l++) { + bool pulseIsLong = isLong(pdec->message[l]); + + // no manchester + if (!(pulseIsLong || isShort(pdec->message[l]))) { + break; + } + + pulseCnt += (pulseIsLong ? 2 : 1); + // probe signal to match manchester + if (pulseIsLong) { + // probe clock based preamble + if (l == i && i > 0) { + int pClock = abs(pdec->pattern[pdec->message[l - 1]]); + + if (pClock < maxPulse && (pdec->pattern[pdec->message[l - 1]] ^ pdec->pattern[pdec->message[l]]) >> 15) + { + int pClocks = round(pClock / (float)clock); + + if (pClocks > 1 && abs(1 - (pClock / (pClocks * (float)clock))) <= 0.07) { +#ifdef DEBUGDECODE + DBG_PRINT(F("preamble:")); DBG_PRINT(pClocks); DBG_PRINT(F("C")); +#endif + pdec->mstart--; + preamble = true; + break; + } + } + } + + ht = ((pulseCnt & 0x1) == 0); +#ifdef DEBUGDECODE + if (ht) { + DBG_PRINT(F("pulseShift:")); DBG_PRINT(l); DBG_PRINT(";"); + } +#endif + break; + } + } + + // interpret first long as short if preamble was found + if (preamble) { + ht = true; + i++; + continue; + } + } - // Sync to a long pulse to detect 0 / 1 proper + // Sync to a long or short pulse + /* if (mc_start_found && !mc_sync) { - while (!isLong(pdec->message[i]) && i < pdec->messageLen) { - i++; - } - if (i < pdec->messageLen) { - lastbit = (char)((unsigned int)pdec->pattern[pdec->message[i]] >> 15); - uint8_t z = i - pdec->mstart; - if ((z < 1) or ((z % 2) == 0)) - i = pdec->mstart; - else - i = pdec->mstart + 1; - //ManchesterBits->addValue((lastbit)); - mc_sync = true; - //i++; - } + while ( (!isShort(pdec->message[i] || !isLong(pdec->message[i])) && i < pdec->messageLen) { + i++; } - + if (i < pdec->messageLen) { + lastbit = (char)((unsigned int)pdec->pattern[pdec->message[i]] >> 15); // 1, wenn Pegel Low war, 0 bei einem High Pegel. + //lastbit = ~lastbit; //TODO: Pruefen ob negiert korrekt ist. + + uint8_t z = i - pdec->mstart; + if ((z < 1) or ((z % 2) == 0)) + i = pdec->mstart; + else + i = pdec->mstart + 1; + //ManchesterBits->addValue((lastbit)); + mc_sync = true; + //i++; + //MSG_PRINT("lb:"); MSG_PRINT(lastbit,DEC); + } + } + */ // Decoding occures here if (mc_sync && mc_start_found) { - if (isLong(pdec->message[i])) { - //ManchesterBits->addValue(!(pdec->pattern[pdec->message[i]][0] >>15)); // Check if bit 16 is set - //ManchesterBits->addValue(1 ^ ((unsigned int)pdec->pattern[pdec->message[i]][0] >> 15))); - lastbit = lastbit ^ 1; #ifdef DEBUGDECODE - //ManchesterBits->addValue(lastbit); - Serial.print("L"); + char value; #endif - } - else if (isShort(pdec->message[i]) && i < pdec->messageLen - 1 && isShort(pdec->message[i + 1])) + if (isShort(pdec->message[i])) //Todo: Check for second short { - - i++; - //ManchesterBits->addValue(!(pdec->pattern[pdec->message[i+1]][0] >>15)); // Check if bit 16 is set - // ManchesterBits->addValue(1 ^ ((unsigned int)pdec->pattern[pdec->message[i]][0] >> 15))); + hasbit = ht; + ht = !ht; #ifdef DEBUGDECODE - Serial.print("SS"); + value = 'S'; #endif + } + else if (isLong(pdec->message[i])) { + hasbit = true; + ht = true; +#ifdef DEBUGDECODE + value = 'L'; +#endif } else { // Found something that fits not to our manchester signal #ifdef DEBUGDECODE - Serial.print("H("); - Serial.print("vcnt:"); - Serial.print(ManchesterBits.valcount); + DBG_PRINT("H("); + DBG_PRINT("vcnt:"); + DBG_PRINT(ManchesterBits.valcount); #endif - //if (i < pdec->messageLen-minbitlen) + //if (i < pdec->messageLen-minbitlen) if (ManchesterBits.valcount < minbitlen) { - if (isShort(pdec->message[i]) && i < pdec->messageLen - 1 && !isShort(pdec->message[i + 1])) { - // unequal number of short pulses. Restart, but one pulse ahead i is incremented at end of while loop - i = pdec->mstart; - } + // if (isShort(pdec->message[i]) && i < pdec->messageLen - 1 && !isShort(pdec->message[i + 1])) { + // // unequal number of short pulses. Restart, but one pulse ahead i is incremented at end of while loop + // i = pdec->mstart; + // } //pdec->mstart=i; mc_start_found = false; // Reset to find new starting position mc_sync = false; + ht = false; // reset short count too #ifdef DEBUGDECODE - Serial.print(":RES:"); + MSG_PRINT(":RES:"); #endif ManchesterBits.reset(); - } else { - pdec->mend = i; - if (isShort(pdec->message[i]) && i == maxMsgSize - 1) { - pdec->mend--; - } + } + else { + pdec->mend = i - (ht ? 0 : 1); // keep short in buffer + // if (isShort(pdec->message[i]) && i == maxMsgSize - 1)) { + // pdec->mend--; + // } #ifdef DEBUGDECODE - Serial.print(":mpos:"); - Serial.print(i); - Serial.print(":mstart:"); - Serial.print(pdec->mstart); - Serial.print(":mend:"); - Serial.print(pdec->mend); - Serial.print(":found:"); -#endif - pdec->bufferMove(pdec->mend); - pdec->m_truncated = true; // Flag that we truncated the message array and want to receiver some more data - //if (i+minbitlen > pdec->messageLen) - /* - if ( isShort(pdec->message[pdec->messageLen]) ) - { + DBG_PRINT(":mpos="); + DBG_PRINT(i); + DBG_PRINT(":mstart="); + DBG_PRINT(pdec->mstart); + DBG_PRINT(":mend:"); + DBG_PRINT(pdec->mend); + DBG_PRINT(":mlen:"); + DBG_PRINT(pdec->messageLen); + DBG_PRINT(":found:"); + DBG_PRINT(":pidx="); + DBG_PRINT(pdec->message[i]); + //DBG_PRINT(pdec->pattern[pdec->message[i]]); - pdec->mcDetected = true; - return false; - } - */ +#endif + //pdec->printOut(); + pdec->bufferMove(i); // Todo: BufferMove könnte in die Serielle Ausgabe verschoben werden, das würde ein paar Mikrosekunden Zeit sparen + //pdec->m_truncated = true; // Flag that we truncated the message array and want to receiver some more data + mc_start_found = false; // This will break serval unit tests. Normaly setting this to false shoud be done by reset, needs to be checked if reset shoud be called after hex string is printed out + + //if (i+minbitlen > pdec->messageLen) + /* + if ( isShort(pdec->message[pdec->messageLen]) ) + { + + pdec->mcDetected = true; + return false; + } + */ return (ManchesterBits.valcount >= minbitlen); // Min 20 Bits needed } #ifdef DEBUGDECODE - Serial.print(")"); + MSG_PRINT(")"); +#endif + } + + + if (mc_start_found) { // don't write if manchester processing was canceled +#ifdef DEBUGDECODE + if (pdec->pattern[pdec->message[i]] < 0) + value = (value + 0x20); //lowwecase + DBG_PRINT(value); +#endif + + if (hasbit) { + ManchesterBits.addValue((pdec->pattern[pdec->message[i]] > 0 ? 1 : 0)); +#ifdef DEBUGDECODE + DBG_PRINT(ManchesterBits.getValue(ManchesterBits.valcount - 1)); +#endif + hasbit = false; + } + else { +#ifdef DEBUGDECODE + DBG_PRINT("_"); #endif + } } - if (mc_sync) - ManchesterBits.addValue(lastbit); } - //Serial.print(" S MC "); + //MSG_PRINT(" S MC "); i++; } - pdec->mend = i; + pdec->mend = i - (ht ? 0 : 1); // keep short in buffer; #ifdef DEBUGDECODE - Serial.print(":mpos:"); - Serial.print(i); - Serial.print(":mstart:"); - Serial.print(pdec->mstart); - Serial.print(":mend:"); - Serial.print(pdec->mend); - Serial.print(":vcnt:"); - Serial.print(ManchesterBits.valcount); - Serial.print(":bfin:"); + DBG_PRINT(":mpos="); + DBG_PRINT(i); + DBG_PRINT(":mstart="); + DBG_PRINT(pdec->mstart); + DBG_PRINT(":mend="); + DBG_PRINT(pdec->mend); + DBG_PRINT(":vcnt="); + DBG_PRINT(ManchesterBits.valcount - 1); + DBG_PRINT(":bfin:"); #endif // Check if last entry in our message array belongs to our manchester signal - if (i == maxMsgSize && i == pdec->messageLen && pdec->mstart > 1 && ManchesterBits.valcount > minbitlen / 2) + if (i == maxMsgSize && i == pdec->messageLen && pdec->mstart > 0 && ManchesterBits.valcount > minbitlen / 2) { #ifdef DEBUGDECODE - Serial.print(":bmove:"); + DBG_PRINT(":bmove:"); #endif pdec->bufferMove(pdec->mstart); - pdec->m_truncated = true; // Flag that we truncated the message array and want to receiver some more data - + //pdec->m_truncated = true; // Flag that we truncated the message array and want to receiver some more data + pdec->mcDetected = true; return false; } @@ -1178,16 +1376,18 @@ const bool ManchesterpatternDecoder::doDecode() { { pdec->mcDetected = true; pdec->messageLen = 0; - pdec->m_truncated = true; // Flag that we truncated the message array and want to receiver some more data + pdec->message.reset(); + //pdec->m_truncated = true; // Flag that we truncated the message array and want to receiver some more data #ifdef DEBUGDECODE - Serial.print(":bflush:"); + DBG_PRINT(":bflush:"); + #endif return false; } return (ManchesterBits.valcount >= minbitlen); // Min 20 Bits needed, then return true, otherwise false - //Serial.print(" ES MC "); + //MSG_PRINT(" ES MC "); } /** @brief (Verifies if found signal data is a valid manchester signal, returns true or false) @@ -1197,9 +1397,12 @@ const bool ManchesterpatternDecoder::doDecode() { const bool ManchesterpatternDecoder::isManchester() { - // Durchsuchen aller Musterpulse und prüft ob darin eine clock vorhanden ist + // Durchsuchen aller Musterpulse und prueft ob darin eine clock vorhanden ist #if DEBUGDETECT >= 1 - Serial.print(" -- chk MC -- "); + DBG_PRINTLN(""); + DBG_PRINTLN(" -- chk MC -- "); + DBG_PRINT("mstart:"); + DBG_PRINTLN(pdec->mstart); #endif if (pdec->patternLen < 4) return false; @@ -1207,77 +1410,186 @@ const bool ManchesterpatternDecoder::isManchester() uint8_t pos_cnt = 0; uint8_t neg_cnt = 0; - uint8_t equal_cnt = 0; - const uint8_t minHistocnt = pdec->messageLen*0.04; + int equal_cnt = 0; + const uint8_t minHistocnt = round(pdec->messageLen*0.04); + // 3 1 0 2 + uint8_t sortedPattern[maxNumPattern]; // 1300,-1300,-734,..800 + uint8_t p = 0; - for (uint8_t i = 0; i< pdec->patternLen; i++) + for (uint8_t i = 0; i < pdec->patternLen; i++) { + if (pdec->histo[i] < minHistocnt) continue; // Skip this pattern, due to less occurence in our message #if DEBUGDETECT >= 1 - Serial.print(i); Serial.print(" "); -#endif + MSG_PRINT(p); +#endif - if (pdec->histo[i] < minHistocnt) continue; // Skip this pattern, due to less occurence in our message - const int aktpulse = pdec->pattern[i]; - //if (longlow == -1) - // longlow=longhigh=shortlow=shorthigh=i; // Init to first valid mc index to allow further ajustment + uint8_t ptmp = p; + + while (p != 0 && pdec->pattern[i] < pdec->pattern[sortedPattern[p - 1]]) + { + sortedPattern[p] = sortedPattern[p - 1]; + p--; + } +#if DEBUGDETECT >= 1 + DBG_PRINT("="); DBG_PRINT(i); DBG_PRINT(","); +#endif + sortedPattern[p] = i; + p = ptmp + 1; + } +#if DEBUGDETECT >= 3 + DBG_PRINT("Sorted:"); + for (uint8_t i = 0; i < p; i++) + { + DBG_PRINT(sortedPattern[i]); DBG_PRINT(","); + } + DBG_PRINT(";"); +#endif - if (aktpulse > 0) + for (uint8_t i = 0; ipattern[sortedPattern[i]] <= 0) continue; +#if DEBUGDETECT >= 2 + DBG_PRINT("CLK="); DBG_PRINT(sortedPattern[i]); DBG_PRINT(":"); +#endif + longlow = -1; + longhigh = -1; + shortlow = -1; + shorthigh = -1; + pos_cnt = 0; + neg_cnt = 0; + tstclock = -1; + equal_cnt = 0; + + const int clockpulse = pdec->pattern[sortedPattern[i]]; + for (uint8_t x = 0; x < p; x++) { - equal_cnt += pdec->histo[i]; - pos_cnt++; - tstclock += aktpulse; +#if DEBUGDETECT >= 1 + DBG_PRINT(sortedPattern[x]); +#endif - longhigh = longhigh == -1 || pdec->pattern[longhigh] < aktpulse ? i : longhigh; - shorthigh = shorthigh == -1 || pdec->pattern[shorthigh] > aktpulse ? i : shorthigh; + const int aktpulse = pdec->pattern[sortedPattern[x]]; + bool pshort = false; + bool plong = false; - } - else { - equal_cnt -= pdec->histo[i]; - neg_cnt++; + if (pdec->inTol(clockpulse, abs(aktpulse), clockpulse*0.5)) + pshort = true; + else if (pdec->inTol(clockpulse * 2, abs(aktpulse), clockpulse*0.80)) + plong = true; - longlow = longlow == -1 || pdec->pattern[longlow] > aktpulse ? i : longlow; - shortlow = shortlow == -1 || pdec->pattern[shortlow] < aktpulse ? i : shortlow; - } +#if DEBUGDETECT >= 3 + DBG_PRINT("^=(PS="); DBG_PRINT(pshort); DBG_PRINT(";"); + DBG_PRINT("PL="); DBG_PRINT(plong); DBG_PRINT(";)"); +#endif +#if DEBUGDETECT >= 1 + DBG_PRINT(","); +#endif - } + if (aktpulse > 0) + { + if (pshort) shorthigh = sortedPattern[x]; + else if (plong) longhigh = sortedPattern[x]; + else continue; + //equal_cnt += pdec->histo[sortedPattern[x]]; + + pos_cnt++; + tstclock += aktpulse; + } + else { + if (pshort) shortlow = sortedPattern[x]; + else if (plong) longlow = sortedPattern[x]; + else continue; + + //equal_cnt -= pdec->histo[sortedPattern[x]]; + neg_cnt++; + tstclock -= aktpulse; + + } + + //TODO: equal_cnt sollte nur ueber die validen Pulse errechnet werden Signale nur aus 3 Pulsen sind auch valide (FFFF)... + + if ((longlow != -1) && (shortlow != -1) && (longhigh != -1) && (shorthigh != -1)) + { #if DEBUGDETECT >= 1 - Serial.print("equalcnt: "); Serial.print(equal_cnt); + DBG_PRINT("vfy "); #endif - if (equal_cnt > pdec->messageLen*0.02) return false; + int z = 0; + while (z < pdec->messageLen) + { + + if (((isLong(pdec->message[z]) == false) && (isShort(pdec->message[z]) == false)) || (z == (pdec->messageLen - 1))) + { #if DEBUGDETECT >= 1 - Serial.print(" MC equalcnt matched"); + DBG_PRINT(z); DBG_PRINT("=")DBG_PRINT(pdec->message[z]); DBG_PRINT(";") + + DBG_PRINT("Long"); DBG_PRINT(isLong(pdec->message[z])); DBG_PRINT(";"); + DBG_PRINT("Short"); DBG_PRINT(isShort(pdec->message[z])); DBG_PRINTLN(";"); + #endif + if ((z - pdec->mstart) > minbitlen) // Todo: Hier wird auf minbitlen geprueft. Die Differenz zwischen mstart und mend sind aber Pulse und keine bits + { + pdec->mend = z; + + pdec->calcHisto(pdec->mstart, pdec->mend); + equal_cnt = pdec->histo[shorthigh] + pdec->histo[longhigh] - pdec->histo[shortlow] - pdec->histo[longlow]; - if (neg_cnt != pos_cnt) return false; // Both must be 2 #if DEBUGDETECT >= 1 - Serial.print(" MC neg and pos pattern cnt is equal"); + DBG_PRINT("equalcnt: pos "); DBG_PRINT(pdec->mstart); DBG_PRINT(" to ") DBG_PRINT(pdec->mend); DBG_PRINT("count="); DBG_PRINT(equal_cnt); DBG_PRINT(" "); +#endif + mc_start_found = false; + if (abs(equal_cnt) > round(pdec->messageLen*0.04)) break; //Next loop +#if DEBUGDETECT >= 1 + DBG_PRINT(" MC equalcnt matched"); +#endif + if (neg_cnt != pos_cnt) break; // Both must be 2 //TODO: For FFFF we have only 3 valid pulses! +#if DEBUGDETECT >= 1 + DBG_PRINT(" MC neg and pos pattern cnt is equal"); #endif - tstclock = tstclock / 3; + if ((longlow == longhigh) || (shortlow == shorthigh) || (longlow == shortlow) || (longhigh == shorthigh) || (longlow == shorthigh) || (longhigh == shortlow)) break; //Check if the indexes are valid + + tstclock = tstclock / 6; #if DEBUGDETECT >= 1 - Serial.print(" tstclock: "); Serial.print(tstclock); + MSG_PRINT(" tstclock: "); DBG_PRINT(tstclock); #endif - clock = tstclock; - // dclock=clock*2; + clock = tstclock; #if DEBUGDETECT >= 1 - Serial.print(" MC LL:"); Serial.print(longlow); - Serial.print(", MC LH:"); Serial.print(longhigh); + DBG_PRINT(" MC LL:"); DBG_PRINT(longlow); + DBG_PRINT(", MC LH:"); DBG_PRINT(longhigh); - Serial.print(", MC SL:"); Serial.print(shortlow); - Serial.print(", MC SH:"); Serial.print(shorthigh); - Serial.println(""); + DBG_PRINT(", MC SL:"); DBG_PRINT(shortlow); + DBG_PRINT(", MC SH:"); DBG_PRINT(shorthigh); + DBG_PRINTLN(""); #endif - if ((longlow == -1) || (shortlow == -1) || (longlow == shortlow) || (longhigh == -1) || (shorthigh == -1) || (longhigh == shorthigh)) return false; //Check if the indexes are valid - - if ((longlow == longhigh) || (shortlow == shorthigh) || (longlow == shortlow) || (longhigh == shorthigh) || (longlow == shorthigh) || (longhigh == shortlow)) return false; //Check if the indexes are valid + // TOdo: Bei FFFF passt diese Pruefung nicht. #if DEBUGDETECT >= 1 - Serial.println(" -- MC found -- "); + DBG_PRINTLN(" -- MC found -- "); #endif + return true; + } + else { + mc_start_found = false; + mc_sync = false; + } + } + else { + if (mc_start_found == false) + { + pdec->mstart = z; + mc_start_found = true; + } + } + z++; + } + } + } + + } + return false; - return true; -} + +} diff --git a/src/_micro-api/libraries/signalDecoder/src/signalDecoder.h b/src/_micro-api/libraries/signalDecoder/src/signalDecoder.h index 4eaf093..bf8b1a6 100644 --- a/src/_micro-api/libraries/signalDecoder/src/signalDecoder.h +++ b/src/_micro-api/libraries/signalDecoder/src/signalDecoder.h @@ -2,8 +2,7 @@ * Pattern Decoder Library V3 * Library to decode radio signals based on patternd detection * 2014-2015 N.Butzek, S.Butzek -* 2015 S.Butzek -* 2016 S.Butzek +* 2015-2017 S.Butzek * This library contains different classes to perform detecting of digital signals * typical for home automation. The focus for the moment is on different sensors @@ -33,23 +32,20 @@ #define _SIGNALDECODER_h #if defined(ARDUINO) && ARDUINO >= 100 - #include "Arduino.h" +#include "Arduino.h" #else - #include "WProgram.h" +#include "WProgram.h" #endif +#define DEBUG 1 +#include "output.h" +#include "bitstore.h" +#include "FastDelegate.h" - - - - - -#include - -#define maxNumPattern 6 +#define maxNumPattern 8 #define maxMsgSize 254 #define minMessageLen 40 -#define syncMinFact 7 +#define syncMinFact 6 #define syncMaxFact 39 #define syncMaxMicros 17000 #define maxPulse 32001 // Magic Pulse Length @@ -58,56 +54,69 @@ #define SERIAL_DELIMITER ';' #define MSG_START char(0x2) // this is a non printable Char #define MSG_END char(0x3) // this is a non printable Char - - - -//#define DEBUGDETECT 4 +//#define DEBUGDETECT 1 //#define DEBUGDETECT 255 // Very verbose output -//#define DEBUGDECODE 2 +//#define DEBUGDECODE 1 enum status { searching, clockfound, syncfound, detecting }; + + class SignalDetectorClass { friend class ManchesterpatternDecoder; public: - SignalDetectorClass() : first(buffer), last(first + 1) { buffer[0] = buffer[1] = 0; reset(); }; + SignalDetectorClass() : first(buffer), last(first + 1), message(4) { + buffer[0] = 0; reset(); mcMinBitLen = 17; + MsMoveCount = 0; + MredEnabled = 1; // 1 = compress printmsg + }; void reset(); bool decode(const int* pulse); const status getState(); + typedef fastdelegate::FastDelegate0 FuncRetuint8t; + void setRSSICallback(FuncRetuint8t callbackfunction) { _rssiCallback = callbackfunction; } + + //private: int8_t clock; // index to clock in pattern bool MUenabled; bool MCenabled; bool MSenabled; - int8_t histo[maxNumPattern]; - uint8_t message[maxMsgSize]; - uint8_t messageLen; - uint8_t mstart; // Holds starting point for message - uint8_t mend; // Holds end point for message if detected - bool success; // True if a valid coding was found - - bool m_truncated; // Identify if message has been truncated + bool MredEnabled; // 1 = compress printMsgRaw + uint8_t MsMoveCount; + + uint8_t histo[maxNumPattern]; + //uint8_t message[maxMsgSize]; + BitStore message; // A store using 4 bit for every value stored. + + uint8_t messageLen; // Todo, kann durch message.valcount ersetzt werden + uint8_t mstart; // Holds starting point for message + uint8_t mend; // Holds end point for message if detected + bool success; // True if a valid coding was found + bool m_truncated; // Identify if message has been truncated bool m_overflow; void bufferMove(const uint8_t start); uint16_t tol; // calculated tolerance for signal - uint8_t bitcnt; + //uint8_t bitcnt; status state; // holds the status of the detector - int buffer[2]; // Internal buffer to store two pules length + int buffer[1]; // Internal buffer to store two pules length int* first; // Pointer to first buffer entry int* last; // Pointer to last buffer entry float tolFact; // int pattern[maxNumPattern]; // 1d array to store the pattern uint8_t patternLen; // counter for length of pattern uint8_t pattern_pos; - int8_t sync; // index to sync in pattern if it exists - String preamble; - String postamble; + int8_t sync; // index to sync in pattern if it exists + //String preamble; + //String postamble; bool mcDetected; // MC Signal alread detected flag - + uint8_t mcMinBitLen; // min bit Length + uint8_t rssiValue; // Holds the RSSI value retrieved via a rssi callback + FuncRetuint8t _rssiCallback; // Holds the pointer to a callback Function void addData(const uint8_t value); void addPattern(); @@ -126,9 +135,7 @@ class SignalDetectorClass void printOut(); int8_t findpatt(const int val); // Finds a pattern in our pattern store. returns -1 if te pattern is not found - //bool validSequence(const int *a, const int *b); // checks if two pulses are basically valid in terms of on-off signals - - + //bool validSequence(const int *a, const int *b); // checks if two pulses are basically valid in terms of on-off signals }; @@ -145,10 +152,13 @@ class ManchesterpatternDecoder void getMessageClockStr(String* str); void getMessageLenStr(String* str); + void printMessageHexStr(); + void printMessagePulseStr(); + const bool isManchester(); void reset(); #ifndef UNITTEST -//private: + //private: #endif BitStore<50> ManchesterBits; // A store using 1 bit for every value stored. It's used for storing the Manchester bit data in a efficent way SignalDetectorClass *pdec; @@ -158,7 +168,7 @@ class ManchesterpatternDecoder int8_t shorthigh; int clock; // Manchester calculated clock int8_t minbitlen; - + bool mc_start_found = false; bool mc_sync = false; @@ -169,4 +179,3 @@ class ManchesterpatternDecoder #endif - From 1df736e07c289c8172d6a777397abf9c9fdf5148 Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Fri, 18 Aug 2017 23:47:04 +0200 Subject: [PATCH 11/40] Updated BitStore --- .../libraries/bitstore/src/bitstore.h | 307 +++++++++++++----- 1 file changed, 226 insertions(+), 81 deletions(-) diff --git a/src/_micro-api/libraries/bitstore/src/bitstore.h b/src/_micro-api/libraries/bitstore/src/bitstore.h index 780fb69..8bce811 100644 --- a/src/_micro-api/libraries/bitstore/src/bitstore.h +++ b/src/_micro-api/libraries/bitstore/src/bitstore.h @@ -1,6 +1,6 @@ /* * Library for storing and retrieving multibple bits in one byte -* Copyright (C) 2014 S.Butzek +* Copyright (C) 2014-2017 S.Butzek * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,27 +24,44 @@ template class BitStore { - public: - /** Default constructor */ - BitStore(uint8_t bitlength); - //~BitStore(); - void addValue(char value); - unsigned char getValue(uint8_t pos); - const uint8_t getSize(); - //unsigned char *datastore; // Reserve 40 Bytes for our store. Should be edited to aa dynamic way - unsigned char datastore[bufSize]; - void reset(); - unsigned char getByte(uint8_t idx); - uint8_t bytecount; // Number of stored bytes - uint8_t valcount; // Number of total values stored - protected: - - private: - uint8_t valuelen; // Number of bits for every value - uint8_t bmask; - uint8_t bcnt; - const uint8_t buffsize; +public: + /** Default constructor */ + BitStore(uint8_t bitlength); + //~BitStore(); + bool addValue(byte value); + int8_t getValue(const uint16_t pos); + bool moveLeft(const uint16_t begin); + bool changeValue(const uint16_t pos, byte value); + + const uint16_t getSize(); + //unsigned char *datastore; // Reserve 40 Bytes for our store. Should be edited to aa dynamic way + unsigned char datastore[bufSize]; + void reset(); + bool getByte(const uint8_t idx, uint8_t *retvalue); + uint8_t bytecount; // Number of stored bytes + uint16_t valcount; // Number of total values stored + + int8_t operator[](const uint16_t pos) { + getValue(pos); + return _rval; + } + BitStore &operator+=(const int8_t value) { + addValue(value); + return *this; + } + + + +#ifndef UNITTEST +protected: +private: +#endif + uint8_t valuelen; // Number of bits for every value + uint8_t bmask; + uint8_t bcnt; + const uint8_t buffsize; + byte _rval; }; @@ -67,94 +84,222 @@ class BitStore */ template -BitStore::BitStore(uint8_t bitlength):buffsize(bufSize) +BitStore::BitStore(uint8_t bitlength) :buffsize(bufSize) { - valuelen = bitlength; // How many bits shoudl be reserved for one value added ? - bmask=0; - //buffsize = bufsize; - //datastore= (unsigned char*) calloc(bufsize,sizeof(char)); // Speicher allokieren und 0 zuweisen - reset(); - for (uint8_t x=7;x>(7-valuelen);x--) - { - bmask = bmask | (1<(7 - valuelen); x--) + { + bmask = bmask | (1 << x); + } } /** @brief (one liner) - * - * (documentation goes here) - */ +* +* (documentation goes here) +*/ /*template - BitStore::~BitStore() +BitStore::~BitStore() { - //free(datastore); +//free(datastore); } */ template +bool BitStore::addValue(byte value) +{ + if (bcnt == 7 && valcount > 0) + { + if (bytecount >= buffsize - 1) { + //Serial.println("OOB"); + return false; // Out of Buffer + } + bytecount++; + datastore[bytecount] = 0; + } + //Serial.print("Adding value:"); Serial.print(value, DEC); + //Serial.print(" ("); Serial.print(value, BIN); Serial.print(") "); + //store[bytecount]=datastore[bytecount] | (value<= 0) // Soalnge nicht 8 Bit gepeichert wurden, erhoehen wir den counter zum verschieben + { + bcnt = bcnt - valuelen; //+valuelen + } + else { + bcnt = 7; + } + return true; + //Serial.println(""); +} -void BitStore::addValue(char value) + +template +bool BitStore::changeValue(const uint16_t pos, byte value) { - if (bytecount >=buffsize ) return; // Out of Buffer - //store[bytecount]=datastore[bytecount] | (value<= buffsize - 1) return false; // Out of Buffer + // Serial.print("Pos:"); Serial.print(pos, DEC); + // 01 11 11 00 10 + + value <<= (8 - (pos*valuelen % 8) - valuelen); // shift bits in value to new positon + //Serial.print(" new_value(bin)"); Serial.print(value, BIN); + + datastore[bytepos] = datastore[bytepos] & ~(bmask >> (pos*valuelen % 8)); // Clear bits to be changed + datastore[bytepos] = datastore[bytepos] | value; // Apply new bits + + /* + Serial.print(" -> "); + Serial.print(" datastore to (bin)"); Serial.print(datastore[bytepos], BIN); + Serial.print(" (valuelen)"); Serial.println(valuelen, DEC); + */ + + return true; +} + +/** @brief (return the last position with a value) +* +* (returns the variable valcount. This represents the number of values ) */ - valcount++; - if ((bcnt-valuelen) >= 0) // Soalnge nicht 8 Bit geppeichert wurden, erhöhen wir den counter zum verschieben - { - bcnt=bcnt-valuelen; //+valuelen - } else { - bcnt=7; - bytecount++; - datastore[bytecount]=0; - } +template +const uint16_t BitStore::getSize() +{ + return valcount; } + template -const uint8_t BitStore::getSize() +bool BitStore::moveLeft(const uint16_t begin) { - return valcount; + if (begin == 0 || begin > valcount - 1) return false; + + uint8_t startbyte = begin*valuelen / 8; + /* + Serial.print("moveleft startbyte:"); Serial.print(startbyte, DEC); Serial.print("@valpos"); Serial.print(begin, DEC); + Serial.print(" bytecount:"); Serial.print(bytecount, DEC); + Serial.print(" vlen:"); Serial.print(valuelen, DEC); + */ + if (begin % (8 / valuelen) != 0) { + uint8_t shift_left = (begin % (8 / valuelen))*valuelen; + uint8_t shift_right = 8 - shift_left; + //Serial.print(" sleft "); Serial.print(shift_left, DEC); Serial.print(" sright"); Serial.print(shift_right, DEC); + + valcount = valcount - (shift_left / valuelen); + uint8_t i = startbyte; + uint8_t z = 0; + for (; i < bytecount; ++i, ++z) + { + /* + Serial.println(""); + Serial.print("@["); Serial.print(i, DEC); Serial.print("]"); + Serial.print("->["); Serial.print(z, DEC); Serial.print("] "); + + Serial.print("z="); Serial.print(datastore[z], BIN); + Serial.print(" ileft="); Serial.print(datastore[i] << shift_left, BIN); + Serial.print(" iright="); Serial.print(datastore[i + 1] >> shift_right, BIN); + */ + datastore[z] = (datastore[i] << shift_left) | (datastore[i + 1] >> shift_right);; + + } + datastore[z] = datastore[i] << shift_left; + + valcount = valcount - (8 / valuelen*startbyte); + if ((valcount*valuelen) % 8 == 0) + bcnt = 7; + else + bcnt = 7 - shift_left; + + bytecount = (valcount - 1)*valuelen / 8; + //bcnt = 7-shift_left; + + //bcnt = bcnt - valuelen; // Todo: Klären ob dies benötigt wird + + } + else { + bytecount = bytecount - startbyte; + //Serial.print(" memmove "); Serial.print(bytecount, DEC); Serial.print(" bytes"); + memmove(datastore, datastore + startbyte, sizeof(datastore[0]) * bytecount + 1); + bcnt = 7; + valcount = valcount - (8 / valuelen*startbyte); + } + + /* + Serial.print(" bcnt: "); Serial.print(bcnt, DEC); + Serial.print(" valcount: "); Serial.print(valcount, DEC); + Serial.print(" bytecount: "); Serial.print(bytecount, DEC); + Serial.println(" "); + */ + return true; + } template -unsigned char BitStore::getValue(uint8_t pos) +int8_t BitStore::getValue(const uint16_t pos) { - if ((pos*valuelen/8) >=buffsize ) return -1; // Out of Buffer - - uint8_t mask; // Local modified bitmask - unsigned char ret; - //Serial.print("Bitmask:"); Serial.println(bmask,DEC); - //ret= (datastore[pos*valuelen/8]>>(pos*valuelen%8))&bmask; - mask = bmask >> (pos*valuelen%8); //Mask the position we want to retrieve - ret= datastore[pos*valuelen/8]&mask; // Combine the mask with our store to extract the bit - ret=ret>>(7-(pos*valuelen%8)); // Align the the bits to the right edge - return ret; + int16_t bytepos = pos*valuelen / 8; + if ((bytepos) >= buffsize ) return -1; // Out of Buffer + //Serial.print("getValue Pos:"); Serial.print(pos, DEC); + + uint8_t mask; // Local modified bitmask + //ret= (datastore[pos*valuelen/8]>>(pos*valuelen%8))&bmask; + mask = bmask >> (pos*valuelen % 8); //Mask the position we want to retrieve + //Serial.print(" Bitmask:"); Serial.print(mask, BIN); + + _rval = datastore[bytepos] & mask; // Combine the mask with our store to extract the bit + + byte scnt = 8 - (valuelen*(pos) % 8) - valuelen;// ((pos + 1)*valuelen % 8); // pos*valuelen 0*1/1*1/2*1/../7*1 7/6/5/0 8-1 8-2 8-3 8-8 + //byte scnt = ((pos+1)*valuelen % 8); // 0*4/1*4 + //Serial.print(" datastore[bytepos]: ("); Serial.print(_rval, DEC); Serial.print(") "); Serial.println(_rval, BIN); + //Serial.print(" shift:"); Serial.print(scnt, DEC); + + //_rval = _rval >> abs(8 - (pos + 1)*valuelen) % 8;//(pos + 1)*valuelen % 8; + _rval = _rval >> scnt; + //Serial.print(" return: ("); Serial.print(_rval, DEC); Serial.print(") "); Serial.println(_rval, BIN); + + return _rval; } template -unsigned char BitStore::getByte(uint8_t idx) +bool BitStore::getByte(const uint8_t idx,uint8_t *retvalue) { - if (idx >= buffsize) return -1; // Out of buffer range - return (datastore[idx]); + if (idx >= buffsize ) return false; // Out of buffer range + *retvalue =datastore[idx]; + return true; } template void BitStore::reset() { - for (uint8_t i=0;i Date: Fri, 18 Aug 2017 23:59:15 +0200 Subject: [PATCH 12/40] Updated SIGNALESP.ino and cc1101.h and output.h Imported things from SIGNALduino --- .travis.yml | 1 + SIGNALESP/SIGNALESP.ino | 169 ++++++++++-------- SIGNALESP/__vm/Compile.vmps.xml | 4 +- SIGNALESP/__vm/Configuration.Release.vmps.xml | 2 +- SIGNALESP/cc1101.h | 38 ++-- src/_micro-api/libraries/output/src/output.h | 12 +- 6 files changed, 116 insertions(+), 110 deletions(-) diff --git a/.travis.yml b/.travis.yml index ee24df0..95021fd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,7 @@ install: - ln -s $PWD/src/_micro-api/libraries/output /usr/local/share/arduino/libraries/output - ln -s $PWD/src/_micro-api/libraries/signalDecoder /usr/local/share/arduino/libraries/signalDecoder - ln -s $PWD/src/_micro-api/libraries/SimpleFIFO /usr/local/share/arduino/libraries/simpleFIFO + - ln -s $PWD/src/_micro-api/libraries/fastdelegate /usr/local/share/arduino/libraries/fastdelegate - arduino --install-boards esp8266:esp8266 - arduino --board esp8266:esp8266:generic --save-prefs - arduino --pref "compiler.warning_level=all" --save-prefs diff --git a/SIGNALESP/SIGNALESP.ino b/SIGNALESP/SIGNALESP.ino index ad1d0f2..f583c33 100644 --- a/SIGNALESP/SIGNALESP.ino +++ b/SIGNALESP/SIGNALESP.ino @@ -239,7 +239,7 @@ void loop() { if (!command_available) { cmdstring = ""; } blinkLED = true; } -// yield(); + yield(); if (fifousage < FiFo.count()) fifousage = FiFo.count(); while (FiFo.count()>0) { //Puffer auslesen und an Dekoder uebergeben @@ -247,22 +247,9 @@ void loop() { aktVal = FiFo.dequeue(); state = musterDec.decode(&aktVal); if (state) blinkLED = true; //LED blinken, wenn Meldung dekodiert + yield(); } - if (Serial.available()) { - switch(Serial.read()) { - case 'c': - Serial.println("marc: 0x" + String(cc1101::currentMode(), HEX)); - Serial.println("fifo: " + String(FiFo.count()) + ", max. " + String(fifousage)); - break; - case 'd': - dumpEEPROM(); - break; - case 'u': - Serial.println("uptime: " + uptime()); - break; - } - } } @@ -509,7 +496,8 @@ void send_cmd() void HandleCommand() { - + uint8_t reg; + uint8_t val; #define cmd_Version 'V' #define cmd_freeRam 'R' #define cmd_intertechno 'i' @@ -521,14 +509,13 @@ void HandleCommand() #define cmd_send 'S' #define cmd_ping 'P' #define cmd_config 'C' -#define cmd_getConfig 'G' //decrepated #define cmd_buffer 'B' -#define cmd_write 'W' -#define cmd_patable 'x' -#define cmd_ccFactoryReset 'e' -#define cmd_read 'r' +#define cmd_write 'W' // write EEPROM und write CC1101 register +#define cmd_read 'r' // read EEPROM +#define cmd_patable 'x' +#define cmd_ccFactoryReset 'e' // EEPROM / factory reset - uint8_t reg, val; + if (cmdstring.charAt(0) == cmd_ping) { getPing(); @@ -536,7 +523,6 @@ void HandleCommand() else if (cmdstring.charAt(0) == cmd_help) { MSG_PRINT(cmd_help); MSG_PRINT(F(" Use one of ")); MSG_PRINT(cmd_Version); MSG_PRINT(cmd_space); - MSG_PRINT(cmd_intertechno); MSG_PRINT(cmd_space); MSG_PRINT(cmd_freeRam); MSG_PRINT(cmd_space); MSG_PRINT(cmd_uptime); MSG_PRINT(cmd_space); MSG_PRINT(cmd_changeReceiver); MSG_PRINT(cmd_space); @@ -544,9 +530,12 @@ void HandleCommand() MSG_PRINT(cmd_send); MSG_PRINT(cmd_space); MSG_PRINT(cmd_ping); MSG_PRINT(cmd_space); MSG_PRINT(cmd_config); MSG_PRINT(cmd_space); - MSG_PRINT(cmd_getConfig); MSG_PRINT(cmd_space); //decrepated - MSG_PRINT(cmd_buffer); MSG_PRINT(cmd_space); //decrepated - + MSG_PRINT(cmd_read); MSG_PRINT(cmd_space); + MSG_PRINT(cmd_write); MSG_PRINT(cmd_space); + if (hasCC1101) { + MSG_PRINT(cmd_patable); MSG_PRINT(cmd_space); + MSG_PRINT(cmd_ccFactoryReset); MSG_PRINT(cmd_space); + } MSG_PRINTLN(""); } // V: Version @@ -556,7 +545,7 @@ void HandleCommand() if (hasCC1101) { MSG_PRINT(F("cc1101")); switch(cc1101::chipVersion()) { -// case 0x08: // CC1101_VERSION 0x31 +// case 0x08: // CC1101_VERSION 0x31 case 0x18: // CC1101_VERSION 0xF1 MSG_PRINT(F(" 433MHz")); break; @@ -601,56 +590,71 @@ void HandleCommand() else if (cmdstring.charAt(0) == cmd_changeFilter) { } else if (cmdstring.charAt(0) == cmd_config) { - configCMD(); + if (cmdstring.charAt(1) == 'G') { + getConfig(); + } + else if (cmdstring.charAt(1) == 'E' || cmdstring.charAt(1) == 'D') { //Todo: E und D sind auch hexadezimal, werden hier aber abgefangen + configCMD(); + } + else if (cmdstring.charAt(1) == 'S') { + configSET(); + } + else if (isHexadecimalDigit(cmdstring.charAt(1)) && isHexadecimalDigit(cmdstring.charAt(2)) && hasCC1101) { + reg = cmdstringPos2int(1); + cc1101::readCCreg(reg); + } + else { + MSG_PRINTLN(F("Unsupported command")); + } } - // get config - else if (cmdstring.charAt(0) == cmd_getConfig) { - getConfig(); + else if (cmdstring.charAt(0) == cmd_write) { // write EEPROM und CC11001 register + if (cmdstring.charAt(1) == 'S' && cmdstring.charAt(2) == '3' && hasCC1101) { // WS Command Strobes + cc1101::commandStrobes(); + } + else if (isHexadecimalDigit(cmdstring.charAt(1)) && isHexadecimalDigit(cmdstring.charAt(2)) && isHexadecimalDigit(cmdstring.charAt(3)) && isHexadecimalDigit(cmdstring.charAt(4))) { + reg = cmdstringPos2int(1); + val = cmdstringPos2int(3); + EEPROM.write(reg, val); + if (hasCC1101) { + cc1101::writeCCreg(reg, val); + } + } + else { + MSG_PRINTLN(F("Unsupported command")); + } } - else if (cmdstring.charAt(0) == cmd_buffer) { - MSG_PRINTLN(fifousage); -#ifdef CMP_CC1101 - } else if (cmdstring.charAt(0) == cmd_read && isHexadecimalDigit(cmdstring.charAt(1)) && isHexadecimalDigit(cmdstring.charAt(2))) { // R read EEPROM - reg = cmdstringPos2int(1); - MSG_PRINT(F("EEPROM ")); - printHex2(reg); - if (cmdstring.charAt(3) == 'n') { - MSG_PRINT(F(" :")); - for (uint8_t i = 0; i < 16; i++) { - MSG_PRINT(" "); - printHex2(EEPROM.read(reg + i)); - } - } else { - MSG_PRINT(F(" = ")); - printHex2(EEPROM.read(reg)); - } - MSG_PRINTLN(""); - } else if (cmdstring.charAt(0) == cmd_patable && isHexadecimalDigit(cmdstring.charAt(1)) && isHexadecimalDigit(cmdstring.charAt(2)) && hasCC1101) { - val = cmdstringPos2int(1); - cc1101::writeCCpatable(val); - MSG_PRINT(F("Write ")); - printHex2(val); - MSG_PRINTLN(F(" to PATABLE done")); - EEPROM.commit(); - } else if (cmdstring.charAt(0) == cmd_ccFactoryReset && hasCC1101) { - cc1101::ccFactoryReset(); - cc1101::CCinit(); - EEPROM.commit(); - } else if (cmdstring.charAt(0) == cmd_write) { // write EEPROM und CC11001 register - if (cmdstring.charAt(1) == 'S' && cmdstring.charAt(2) == '3' && hasCC1101) { // WS Command Strobes - cc1101::commandStrobes(); - } else if (isHexadecimalDigit(cmdstring.charAt(1)) && isHexadecimalDigit(cmdstring.charAt(2)) && isHexadecimalDigit(cmdstring.charAt(3)) && isHexadecimalDigit(cmdstring.charAt(4))) { - reg = cmdstringPos2int(1); - val = cmdstringPos2int(3); - if (hasCC1101) { - cc1101::writeCCreg(reg, val); - EEPROM.commit(); - } - } -#endif - } else { + // R read EEPROM + else if (cmdstring.charAt(0) == cmd_read && isHexadecimalDigit(cmdstring.charAt(1)) && isHexadecimalDigit(cmdstring.charAt(2))) { // R read EEPROM + reg = cmdstringPos2int(1); + MSG_PRINT(F("EEPROM ")); + printHex2(reg); + if (cmdstring.charAt(3) == 'n') { + MSG_PRINT(F(" :")); + for (uint8_t i = 0; i < 16; i++) { + MSG_PRINT(" "); + printHex2(EEPROM.read(reg + i)); + } + } + else { + MSG_PRINT(F(" = ")); + printHex2(EEPROM.read(reg)); + } + MSG_PRINTLN(""); + } + else if (cmdstring.charAt(0) == cmd_patable && isHexadecimalDigit(cmdstring.charAt(1)) && isHexadecimalDigit(cmdstring.charAt(2)) && hasCC1101) { + val = cmdstringPos2int(1); + cc1101::writeCCpatable(val); + MSG_PRINT(F("Write ")); + printHex2(val); + MSG_PRINTLN(F(" to PATABLE done")); + } + else if (cmdstring.charAt(0) == cmd_ccFactoryReset && hasCC1101) { + cc1101::ccFactoryReset(); + cc1101::CCinit(); + } + else { MSG_PRINT(F("Unsupported command")); - MSG_PRINTLN(" -> 0x" + String(cmdstring.charAt(0), HEX) + " " + cmdstring); + MSG_PRINTLN(" -> 0x" + String(cmdstring.charAt(0), HEX) + " " + cmdstring); } } @@ -658,17 +662,14 @@ void HandleCommand() void getConfig() { MSG_PRINT(F("MS=")); - //enDisPrint(musterDec.MSenabled); MSG_PRINT(musterDec.MSenabled, DEC); MSG_PRINT(F(";MU=")); - //enDisPrint(musterDec.MUenabled); MSG_PRINT(musterDec.MUenabled, DEC); MSG_PRINT(F(";MC=")); - //enDisPrint(musterDec.MCenabled); MSG_PRINTLN(musterDec.MCenabled, DEC); } - +/* void enDisPrint(bool enDis) { if (enDis) { @@ -678,7 +679,7 @@ void enDisPrint(bool enDis) MSG_PRINT(F("disable")); } } - +*/ void configCMD() { @@ -715,6 +716,16 @@ void configCMD() storeFunctions(musterDec.MSenabled, musterDec.MUenabled, musterDec.MCenabled); } +inline void configSET() +{ + //MSG_PRINT(cmdstring.substring(2, 8)); + if (cmdstring.substring(2, 8) == "mcmbl=") // mc min bit len + { + musterDec.mcMinBitLen = cmdstring.substring(8).toInt(); + MSG_PRINT(musterDec.mcMinBitLen); MSG_PRINT(" bits set"); + } +} + inline void ethernetEvent() { diff --git a/SIGNALESP/__vm/Compile.vmps.xml b/SIGNALESP/__vm/Compile.vmps.xml index 3967e31..d16005c 100644 --- a/SIGNALESP/__vm/Compile.vmps.xml +++ b/SIGNALESP/__vm/Compile.vmps.xml @@ -1,8 +1,8 @@ - + - + diff --git a/SIGNALESP/__vm/Configuration.Release.vmps.xml b/SIGNALESP/__vm/Configuration.Release.vmps.xml index 9a3e5eb..754653a 100644 --- a/SIGNALESP/__vm/Configuration.Release.vmps.xml +++ b/SIGNALESP/__vm/Configuration.Release.vmps.xml @@ -2,7 +2,7 @@ - + diff --git a/SIGNALESP/cc1101.h b/SIGNALESP/cc1101.h index b87bf1a..74d3337 100644 --- a/SIGNALESP/cc1101.h +++ b/SIGNALESP/cc1101.h @@ -108,7 +108,8 @@ namespace cc1101 { #endif #define wait_Miso() while(isHigh(misoPin) ) { static uint8_t miso_count=255;delay(1); if(miso_count==0) return; miso_count--; } // wait until SPI MISO line goes low - + #define wait_Miso_rf() while(isHigh(misoPin) ) { static uint8_t miso_count=255;delay(1); if(miso_count==0) return false; miso_count--; } // wait until SPI MISO line goes low + #define cc1101_Select() digitalLow(csPin) // select (SPI) CC1101 #define cc1101_Deselect() digitalHigh(csPin) @@ -215,18 +216,18 @@ namespace cc1101 { #endif } - uint8_t cmdStrobe(const uint8_t cmd) { // send command strobe to the CC1101 IC via SPI + uint8_t cmdStrobe(const uint8_t cmd) { // send command strobe to the CC1101 IC via SPI cc1101_Select(); // select CC1101 - wait_Miso(); // wait until MISO goes low + wait_Miso_rf(); // wait until MISO goes low uint8_t ret = sendSPI(cmd); // send strobe command - wait_Miso(); // wait until MISO goes low + wait_Miso_rf(); // wait until MISO goes low cc1101_Deselect(); // deselect CC1101 - return ret; // Chip Status Byte + return ret; // Chip Status Byte } uint8_t readReg(const uint8_t regAddr, const uint8_t regType) { // read CC1101 register via SPI cc1101_Select(); // select CC1101 - wait_Miso(); // wait until MISO goes low + wait_Miso_rf(); // wait until MISO goes low sendSPI(regAddr | regType); // send register address uint8_t val = sendSPI(0x00); // read result cc1101_Deselect(); // deselect CC1101 @@ -424,32 +425,17 @@ namespace cc1101 { #ifndef ESP8266 SPCR = _BV(SPE) | _BV(MSTR); // SPI speed = CLK/4 - /* - SPCR = ((1 << SPE) | // SPI Enable - (0 << SPIE) | // SPI Interupt Enable - (0 << DORD) | // Data Order (0:MSB first / 1:LSB first) - (1 << MSTR) | // Master/Slave select - (0 << SPR1) | (0 << SPR0) | // SPI Clock Rate - (0 << CPOL) | // Clock Polarity (0:SCK low / 1:SCK hi when idle) - (0 << CPHA)); // Clock Phase (0:leading / 1:trailing edge sampling) - - SPSR = (1 << SPI2X); // Double Clock Rate - */ + digitalHigh(csPin); // SPI init + digitalHigh(sckPin); + digitalLow(mosiPin); #else SPI.setDataMode(SPI_MODE0); SPI.setBitOrder(MSBFIRST); SPI.begin(); SPI.setClockDivider(SPI_CLOCK_DIV4); #endif - -#ifndef ESP8266 - digitalHigh(csPin); // SPI init - digitalHigh(sckPin); - digitalLow(mosiPin); -#endif - - pinAsInput(PIN_RECEIVE); // gdo2 - pinAsOutput(PIN_SEND); // gdo0Pi, sicherheitshalber bis zum CC1101 init erstmal input + pinAsInput(PIN_RECEIVE); // gdo2 + pinAsOutput(PIN_SEND); // gdo0Pi, sicherheitshalber bis zum CC1101 init erstmal input } uint8_t getRSSI() diff --git a/src/_micro-api/libraries/output/src/output.h b/src/_micro-api/libraries/output/src/output.h index a4bf537..1da7092 100644 --- a/src/_micro-api/libraries/output/src/output.h +++ b/src/_micro-api/libraries/output/src/output.h @@ -25,8 +25,16 @@ #define MSG_PRINT(...) { MSG_PRINTER.print(__VA_ARGS__); } #define MSG_PRINTLN(...) { MSG_PRINTER.println(__VA_ARGS__); } -#define DBG_PRINT(...) { DBG_PRINTER.print(__VA_ARGS__); } -#define DBG_PRINTLN(...) { DBG_PRINTER.println(__VA_ARGS__); } +#define MSG_WRITE(...) { MSG_PRINTER.write(__VA_ARGS__); } + + +#ifdef DEBUG + #define DBG_PRINT(...) { DBG_PRINTER.print(__VA_ARGS__); } + #define DBG_PRINTLN(...) { DBG_PRINTER.println(__VA_ARGS__); } +#else + #define DBG_PRINT(...) + #define DBG_PRINTLN(...) +#endif From 5de1ca2f3b6bc85d727595a6c5bc9d228321063c Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Sat, 19 Aug 2017 00:11:01 +0200 Subject: [PATCH 13/40] Fixed errors without cc1101 --- SIGNALESP/SIGNALESP.ino | 17 ++++++++++++++--- SIGNALESP/__vm/Compile.vmps.xml | 2 +- SIGNALESP/__vm/Configuration.Release.vmps.xml | 2 +- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/SIGNALESP/SIGNALESP.ino b/SIGNALESP/SIGNALESP.ino index f583c33..0cdd77c 100644 --- a/SIGNALESP/SIGNALESP.ino +++ b/SIGNALESP/SIGNALESP.ino @@ -5,7 +5,7 @@ #define VERSION_1 0x33 #define VERSION_2 0x1d -#define CMP_CC1101 +//#define CMP_CC1101 #define PIN_RECEIVE 5 @@ -209,12 +209,16 @@ void setup() { os_timer_setfn(&cronTimer, cronjob, NULL); os_timer_arm(&cronTimer, 31, true); - if (!hasCC1101 || cc1101::regCheck()) { - enableReceive(); +#ifdef comp_cc1101 + if (!hasCC1101 || cc1101::regCheck()) { +#endif + enableReceive(); DBG_PRINTLN(F("receiver enabled")); +#ifdef comp_cc1101 } else { DBG_PRINTLN(F("cc1101 is not correctly set. Please do a factory reset via command e")); } +#endif cmdstring.reserve(40); } @@ -599,14 +603,17 @@ void HandleCommand() else if (cmdstring.charAt(1) == 'S') { configSET(); } +#ifdef comp_cc1101 else if (isHexadecimalDigit(cmdstring.charAt(1)) && isHexadecimalDigit(cmdstring.charAt(2)) && hasCC1101) { reg = cmdstringPos2int(1); cc1101::readCCreg(reg); } +#endif else { MSG_PRINTLN(F("Unsupported command")); } } +#ifdef comp_cc1101 else if (cmdstring.charAt(0) == cmd_write) { // write EEPROM und CC11001 register if (cmdstring.charAt(1) == 'S' && cmdstring.charAt(2) == '3' && hasCC1101) { // WS Command Strobes cc1101::commandStrobes(); @@ -652,6 +659,7 @@ void HandleCommand() cc1101::ccFactoryReset(); cc1101::CCinit(); } +#endif else { MSG_PRINT(F("Unsupported command")); MSG_PRINTLN(" -> 0x" + String(cmdstring.charAt(0), HEX) + " " + cmdstring); @@ -865,6 +873,7 @@ void initEEPROM() { getFunctions(&musterDec.MSenabled, &musterDec.MUenabled, &musterDec.MCenabled); } +#ifdef comp_cc1101 uint8_t cmdstringPos2int(uint8_t pos) { uint8_t val; uint8_t hex; @@ -882,6 +891,8 @@ void printHex2(const byte hex) { // Todo: printf oder scanf nutzen } MSG_PRINT(hex, HEX); } +#endif + String uptime() { String result = ""; diff --git a/SIGNALESP/__vm/Compile.vmps.xml b/SIGNALESP/__vm/Compile.vmps.xml index d16005c..9e02c6c 100644 --- a/SIGNALESP/__vm/Compile.vmps.xml +++ b/SIGNALESP/__vm/Compile.vmps.xml @@ -2,7 +2,7 @@ - + diff --git a/SIGNALESP/__vm/Configuration.Release.vmps.xml b/SIGNALESP/__vm/Configuration.Release.vmps.xml index 754653a..57833f5 100644 --- a/SIGNALESP/__vm/Configuration.Release.vmps.xml +++ b/SIGNALESP/__vm/Configuration.Release.vmps.xml @@ -2,7 +2,7 @@ - + From 78d1d76bad41564850ede924f538e7203829c8d9 Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Sat, 19 Aug 2017 00:40:46 +0200 Subject: [PATCH 14/40] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 271a831..253d077 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Build Status](https://travis-ci.org/RFD-FHEM/SIGNALESP.svg?branch=master)](https://travis-ci.org/RFD-FHEM/SIGNALESP) +[![Build Status](https://travis-ci.org/RFD-FHEM/SIGNALESP.svg?branch=dev-cc1101)](https://travis-ci.org/RFD-FHEM/SIGNALESP) # SIGNALESP uC v3.3 (development version) System to receive digital signals and provide them to other systems pro demodulatiob. Currently tested with 433 MHZ, but not limited to that frequency or media. From e49de4c29a26f31518bd22f70fd102e8ea6649c5 Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Sat, 19 Aug 2017 23:06:36 +0200 Subject: [PATCH 15/40] Update Project files, to include fastDelegate.h #7 --- SIGNALESP/SIGNALESP.vcxproj | 4 +++- SIGNALESP/SIGNALESP.vcxproj.filters | 6 ++++++ SIGNALESP/__vm/Upload.vmps.xml | 4 ++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/SIGNALESP/SIGNALESP.vcxproj b/SIGNALESP/SIGNALESP.vcxproj index f4c8d83..8577887 100644 --- a/SIGNALESP/SIGNALESP.vcxproj +++ b/SIGNALESP/SIGNALESP.vcxproj @@ -61,7 +61,7 @@ true true true - $(ProjectDir)..\src\_micro-api\libraries\bitstore\src;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\DNSServer\src;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\EEPROM;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WebServer\src;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WiFi\src;$(ProjectDir)..\src\_micro-api\libraries\output\src;$(ProjectDir)..\src\_micro-api\libraries\signalDecoder\src;$(ProjectDir)..\src\_micro-api\libraries\SimpleFIFO\src;$(ProjectDir)..\src\_micro-api\libraries\WIFIManager;$(ProjectDir)..\..\..\..\Programme\Arduino\libraries;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries;$(ProjectDir)..\..\..\..\Benutzer\Sven\Documents\Arduino\libraries;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266\libb64;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266\spiffs;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266\umm_malloc;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\variants\generic;$(ProjectDir)..\SIGNALESP;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\tools\sdk\include;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\tools\sdk\lwip\include;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\xtensa-lx106-elf;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\lib\gcc\xtensa-lx106-elf\4.8.2\include;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\tools\sdk\include;%(AdditionalIncludeDirectories) + $(ProjectDir)..\src\_micro-api\libraries\bitstore\src;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\DNSServer\src;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\EEPROM;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WebServer\src;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WiFi\src;$(ProjectDir)..\src\_micro-api\libraries\fastdelegate\src;$(ProjectDir)..\src\_micro-api\libraries\output\src;$(ProjectDir)..\src\_micro-api\libraries\signalDecoder\src;$(ProjectDir)..\src\_micro-api\libraries\SimpleFIFO\src;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\SPI;$(ProjectDir)..\src\_micro-api\libraries\WIFIManager;$(ProjectDir)..\..\..\..\..\..\Programme\Arduino\libraries;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries;$(ProjectDir)..\..\..\Arduino\libraries;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266\libb64;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266\spiffs;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266\umm_malloc;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\variants\generic;$(ProjectDir)..\SIGNALESP;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\tools\sdk\include;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\tools\sdk\lwip\include;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\xtensa-lx106-elf;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\lib\gcc\xtensa-lx106-elf\4.8.2\include;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\tools\sdk\include;%(AdditionalIncludeDirectories) $(ProjectDir)__vm\.SIGNALESP.vsarduino.h;%(ForcedIncludeFiles) false __ESP8266_ESp8266__;__ESP8266_ESP8266__;__ets__;ICACHE_FLASH;F_CPU=80000000L;LWIP_OPEN_SRC;ARDUINO=10803;ARDUINO_ESP8266_ESP01;ARDUINO_ARCH_ESP8266;ESP8266;__cplusplus=201103L;_VMICRO_INTELLISENSE;%(PreprocessorDefinitions) @@ -79,12 +79,14 @@ + Designer + diff --git a/SIGNALESP/SIGNALESP.vcxproj.filters b/SIGNALESP/SIGNALESP.vcxproj.filters index 4003656..9138413 100644 --- a/SIGNALESP/SIGNALESP.vcxproj.filters +++ b/SIGNALESP/SIGNALESP.vcxproj.filters @@ -36,6 +36,12 @@ Header Files + + Header Files + + + Header Files + diff --git a/SIGNALESP/__vm/Upload.vmps.xml b/SIGNALESP/__vm/Upload.vmps.xml index 8311b0e..9e02c6c 100644 --- a/SIGNALESP/__vm/Upload.vmps.xml +++ b/SIGNALESP/__vm/Upload.vmps.xml @@ -1,8 +1,8 @@ - + - + From 1b44a012de276a8df8b02a291dd1d6520f7ab481 Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Sun, 20 Aug 2017 20:56:28 +0200 Subject: [PATCH 16/40] signalDecoder.cpp Added some more yield() to prevent wdt reset --- .../libraries/signalDecoder/src/signalDecoder.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/_micro-api/libraries/signalDecoder/src/signalDecoder.cpp b/src/_micro-api/libraries/signalDecoder/src/signalDecoder.cpp index 85b4a8e..e9fc8e1 100644 --- a/src/_micro-api/libraries/signalDecoder/src/signalDecoder.cpp +++ b/src/_micro-api/libraries/signalDecoder/src/signalDecoder.cpp @@ -97,6 +97,7 @@ inline void SignalDetectorClass::doDetect() //if (messageLen == 0) valid = true; if (!valid) { // Try output + yield(); processMessage(); if (messageLen < minMessageLen) { MsMoveCount = 3; @@ -751,6 +752,7 @@ void SignalDetectorClass::calcHisto(const uint8_t startpos, uint8_t endpos) { histo[i] = 0; } + yield(); if (endpos == 0) endpos = messageLen; /*for (uint8_t i = startpos; i < endpos; i++) @@ -820,6 +822,7 @@ bool SignalDetectorClass::getSync() if (state == clockfound) // we need a clock to find this type of sync { + yield(); // clock wurde bereits durch getclock bestimmt. for (int8_t p = patternLen - 1; p >= 0; --p) // Schleife fuer langen Syncpuls { @@ -847,7 +850,6 @@ bool SignalDetectorClass::getSync() //(syncMinFact*pattern[clock] <= syncabs) ) { - yield(); //if ((syncMinFact* (pattern[clock]) <= -1*pattern[p])) {//n>9 => langer Syncpulse (als 10*int16 darstellbar // Pruefe ob Sync und Clock valide sein koennen // if (histo[p] > 6) continue; // Maximal 6 Sync Pulse Todo: 6 Durch Formel relativ zu messageLen ersetzen @@ -1342,6 +1344,7 @@ const bool ManchesterpatternDecoder::doDecode() { } //MSG_PRINT(" S MC "); i++; + yield(); } pdec->mend = i - (ht ? 0 : 1); // keep short in buffer; @@ -1448,6 +1451,7 @@ const bool ManchesterpatternDecoder::isManchester() for (uint8_t i = 0; ipattern[sortedPattern[i]] <= 0) continue; #if DEBUGDETECT >= 2 DBG_PRINT("CLK="); DBG_PRINT(sortedPattern[i]); DBG_PRINT(":"); From 3e0f6c5d7df8b4f9fa50f2cbb6b81446ef1fbb60 Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Sun, 20 Aug 2017 20:57:07 +0200 Subject: [PATCH 17/40] Updated SPI ports in cc1101.h Added some yield() in SIGNALESP.ino --- SIGNALESP/SIGNALESP.ino | 15 +++++++++++---- SIGNALESP/__vm/.SIGNALESP.vsarduino.h | 5 ++--- SIGNALESP/__vm/Compile.vmps.xml | 4 ++-- SIGNALESP/__vm/Configuration.Release.vmps.xml | 4 ++-- SIGNALESP/__vm/Upload.vmps.xml | 4 ++-- SIGNALESP/cc1101.h | 8 ++++---- 6 files changed, 23 insertions(+), 17 deletions(-) diff --git a/SIGNALESP/SIGNALESP.ino b/SIGNALESP/SIGNALESP.ino index 0cdd77c..982c361 100644 --- a/SIGNALESP/SIGNALESP.ino +++ b/SIGNALESP/SIGNALESP.ino @@ -7,13 +7,17 @@ //#define CMP_CC1101 +#ifdef CMP_CC1101 + #define PIN_RECEIVE 5 +#else + #define PIN_RECEIVE 2 +#endif -#define PIN_RECEIVE 5 #define PIN_LED 16 #define PIN_SEND 4 // gdo0Pin TX out #define BAUDRATE 115200 -#define FIFO_LENGTH 200 -#define DEBUG 1 +#define FIFO_LENGTH 200 +#define DEBUG 1 #define ETHERNET_PRINT @@ -113,7 +117,7 @@ void setup() { //ESP.wdtEnable(2000); Serial.begin(115200); - + Serial.setDebugOutput(true); while (!Serial) delay(90); @@ -826,12 +830,14 @@ void storeFunctions(const int8_t ms, int8_t mu, int8_t mc) mu = mu << 1; mc = mc << 2; int8_t dat = ms | mu | mc; + yield(); EEPROM.write(addr_features, dat); } void getFunctions(bool *ms, bool *mu, bool *mc) { int8_t dat = EEPROM.read(addr_features); + yield(); *ms = bool(dat &(1 << 0)); *mu = bool(dat &(1 << 1)); *mc = bool(dat &(1 << 2)); @@ -850,6 +856,7 @@ void dumpEEPROM() { void initEEPROM() { EEPROM.begin(512); //Max bytes of eeprom to use + yield(); if (EEPROM.read(EE_MAGIC_OFFSET) == VERSION_1 && EEPROM.read(EE_MAGIC_OFFSET + 1) == VERSION_2) { DBG_PRINTLN("Reading values fom eeprom"); diff --git a/SIGNALESP/__vm/.SIGNALESP.vsarduino.h b/SIGNALESP/__vm/.SIGNALESP.vsarduino.h index aa1d8f3..5f02bde 100644 --- a/SIGNALESP/__vm/.SIGNALESP.vsarduino.h +++ b/SIGNALESP/__vm/.SIGNALESP.vsarduino.h @@ -5,7 +5,7 @@ all non-arduino files created by visual micro and all visual studio project or solution files can be freely deleted and are not required to compile a sketch (do not delete your own code!). note: debugger breakpoints are stored in '.sln' or '.asln' files, knowledge of last uploaded breakpoints is stored in the upload.vmps.xml file. Both files are required to continue a previous debug session without needing to compile and upload again - Hardware: Generic ESP8266 Module, Platform=esp8266, Package=esp8266 + Hardware: NodeMCU 1.0 (ESP-12E Module), Platform=esp8266, Package=esp8266 */ #if defined(_VMICRO_INTELLISENSE) @@ -19,7 +19,7 @@ #define F_CPU 80000000L #define LWIP_OPEN_SRC #define ARDUINO 10803 -#define ARDUINO_ESP8266_ESP01 +#define ARDUINO_ESP8266_NODEMCU #define ARDUINO_ARCH_ESP8266 #define ESP8266 #define __cplusplus 201103L @@ -92,7 +92,6 @@ typedef long __PTRDIFF_TYPE__; #include -#include #include #include "..\generic\Common.h" diff --git a/SIGNALESP/__vm/Compile.vmps.xml b/SIGNALESP/__vm/Compile.vmps.xml index 9e02c6c..2d6ad08 100644 --- a/SIGNALESP/__vm/Compile.vmps.xml +++ b/SIGNALESP/__vm/Compile.vmps.xml @@ -1,8 +1,8 @@ - + - + diff --git a/SIGNALESP/__vm/Configuration.Release.vmps.xml b/SIGNALESP/__vm/Configuration.Release.vmps.xml index 57833f5..bed601a 100644 --- a/SIGNALESP/__vm/Configuration.Release.vmps.xml +++ b/SIGNALESP/__vm/Configuration.Release.vmps.xml @@ -1,8 +1,8 @@ - + - + diff --git a/SIGNALESP/__vm/Upload.vmps.xml b/SIGNALESP/__vm/Upload.vmps.xml index 9e02c6c..2d6ad08 100644 --- a/SIGNALESP/__vm/Upload.vmps.xml +++ b/SIGNALESP/__vm/Upload.vmps.xml @@ -1,8 +1,8 @@ - + - + diff --git a/SIGNALESP/cc1101.h b/SIGNALESP/cc1101.h index 74d3337..5684084 100644 --- a/SIGNALESP/cc1101.h +++ b/SIGNALESP/cc1101.h @@ -27,10 +27,10 @@ namespace cc1101 { #define PIN_MARK433 4 // LOW -> 433Mhz | HIGH -> 868Mhz #endif - #define csPin SS // CSN out - #define mosiPin MOSI // MOSI out - #define misoPin MISO // MISO in - #define sckPin SCK // SCLK out + #define csPin 15 // CSN out + #define mosiPin 13 // MOSI out + #define misoPin 12 // MISO in + #define sckPin 14 // SCLK out From 1eb5023fb3645ec2fffb03c7898589164f0ff20f Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Sun, 20 Aug 2017 21:31:17 +0200 Subject: [PATCH 18/40] Fixed compiler flag - caused error when compiling with cc1101 support --- SIGNALESP/SIGNALESP.ino | 4 ++-- SIGNALESP/SIGNALESP.vcxproj | 6 +++--- SIGNALESP/__vm/Compile.vmps.xml | 4 ++-- SIGNALESP/__vm/Configuration.Release.vmps.xml | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/SIGNALESP/SIGNALESP.ino b/SIGNALESP/SIGNALESP.ino index 982c361..64f462d 100644 --- a/SIGNALESP/SIGNALESP.ino +++ b/SIGNALESP/SIGNALESP.ino @@ -5,7 +5,7 @@ #define VERSION_1 0x33 #define VERSION_2 0x1d -//#define CMP_CC1101 +#define CMP_CC1101 #ifdef CMP_CC1101 #define PIN_RECEIVE 5 @@ -880,7 +880,7 @@ void initEEPROM() { getFunctions(&musterDec.MSenabled, &musterDec.MUenabled, &musterDec.MCenabled); } -#ifdef comp_cc1101 +#ifdef CMP_CC1101 uint8_t cmdstringPos2int(uint8_t pos) { uint8_t val; uint8_t hex; diff --git a/SIGNALESP/SIGNALESP.vcxproj b/SIGNALESP/SIGNALESP.vcxproj index 8577887..f7bab75 100644 --- a/SIGNALESP/SIGNALESP.vcxproj +++ b/SIGNALESP/SIGNALESP.vcxproj @@ -61,10 +61,10 @@ true true true - $(ProjectDir)..\src\_micro-api\libraries\bitstore\src;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\DNSServer\src;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\EEPROM;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WebServer\src;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WiFi\src;$(ProjectDir)..\src\_micro-api\libraries\fastdelegate\src;$(ProjectDir)..\src\_micro-api\libraries\output\src;$(ProjectDir)..\src\_micro-api\libraries\signalDecoder\src;$(ProjectDir)..\src\_micro-api\libraries\SimpleFIFO\src;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\SPI;$(ProjectDir)..\src\_micro-api\libraries\WIFIManager;$(ProjectDir)..\..\..\..\..\..\Programme\Arduino\libraries;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries;$(ProjectDir)..\..\..\Arduino\libraries;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266\libb64;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266\spiffs;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266\umm_malloc;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\variants\generic;$(ProjectDir)..\SIGNALESP;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\tools\sdk\include;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\tools\sdk\lwip\include;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\xtensa-lx106-elf;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\lib\gcc\xtensa-lx106-elf\4.8.2\include;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\tools\sdk\include;%(AdditionalIncludeDirectories) + $(ProjectDir)..\src\_micro-api\libraries\bitstore\src;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\DNSServer\src;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\EEPROM;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WebServer\src;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\ESP8266WiFi\src;$(ProjectDir)..\src\_micro-api\libraries\fastdelegate\src;$(ProjectDir)..\src\_micro-api\libraries\output\src;$(ProjectDir)..\src\_micro-api\libraries\signalDecoder\src;$(ProjectDir)..\src\_micro-api\libraries\SimpleFIFO\src;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\SPI;$(ProjectDir)..\src\_micro-api\libraries\WIFIManager;$(ProjectDir)..\..\..\..\..\..\Programme\Arduino\libraries;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries;$(ProjectDir)..\..\..\Arduino\libraries;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266\libb64;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266\spiffs;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\cores\esp8266\umm_malloc;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\variants\nodemcu;$(ProjectDir)..\SIGNALESP;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\tools\sdk\include;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\tools\sdk\lwip\include;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include\c++\4.8.2\xtensa-lx106-elf;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\xtensa-lx106-elf\include;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\tools\xtensa-lx106-elf-gcc\1.20.0-26-gb404fb9-2\lib\gcc\xtensa-lx106-elf\4.8.2\include;C:\Users\sidewinder\AppData\Local\arduino15\packages\esp8266\hardware\esp8266\2.3.0\tools\sdk\include;%(AdditionalIncludeDirectories) $(ProjectDir)__vm\.SIGNALESP.vsarduino.h;%(ForcedIncludeFiles) false - __ESP8266_ESp8266__;__ESP8266_ESP8266__;__ets__;ICACHE_FLASH;F_CPU=80000000L;LWIP_OPEN_SRC;ARDUINO=10803;ARDUINO_ESP8266_ESP01;ARDUINO_ARCH_ESP8266;ESP8266;__cplusplus=201103L;_VMICRO_INTELLISENSE;%(PreprocessorDefinitions) + __ESP8266_ESp8266__;__ESP8266_ESP8266__;__ets__;ICACHE_FLASH;F_CPU=80000000L;LWIP_OPEN_SRC;ARDUINO=10803;ARDUINO_ESP8266_NODEMCU;ARDUINO_ARCH_ESP8266;ESP8266;__cplusplus=201103L;_VMICRO_INTELLISENSE;%(PreprocessorDefinitions) true @@ -100,7 +100,7 @@ - + \ No newline at end of file diff --git a/SIGNALESP/__vm/Compile.vmps.xml b/SIGNALESP/__vm/Compile.vmps.xml index 2d6ad08..a94011d 100644 --- a/SIGNALESP/__vm/Compile.vmps.xml +++ b/SIGNALESP/__vm/Compile.vmps.xml @@ -1,8 +1,8 @@ - + - + diff --git a/SIGNALESP/__vm/Configuration.Release.vmps.xml b/SIGNALESP/__vm/Configuration.Release.vmps.xml index bed601a..36cd4c1 100644 --- a/SIGNALESP/__vm/Configuration.Release.vmps.xml +++ b/SIGNALESP/__vm/Configuration.Release.vmps.xml @@ -2,7 +2,7 @@ - + From 64a29ebdc0e72cb7962f3dd509630c11212adc07 Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Tue, 22 Aug 2017 22:09:47 +0200 Subject: [PATCH 19/40] SIGNALESP.ino initialized rssicallback #7 --- SIGNALESP/SIGNALESP.ino | 4 ++-- SIGNALESP/__vm/Upload.vmps.xml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/SIGNALESP/SIGNALESP.ino b/SIGNALESP/SIGNALESP.ino index 64f462d..ae62b84 100644 --- a/SIGNALESP/SIGNALESP.ino +++ b/SIGNALESP/SIGNALESP.ino @@ -138,9 +138,9 @@ void setup() { if (hasCC1101) { DBG_PRINTLN("CC1101 found"); -// musterDec.setRSSICallback(&cc1101::getRSSI); // Provide the RSSI Callback + musterDec.setRSSICallback(&cc1101::getRSSI); // Provide the RSSI Callback }// else -// musterDec.setRSSICallback(&rssiCallback); // Provide the RSSI Callback + musterDec.setRSSICallback(&rssiCallback); // Provide the RSSI Callback #endif #ifdef DEBUG diff --git a/SIGNALESP/__vm/Upload.vmps.xml b/SIGNALESP/__vm/Upload.vmps.xml index 2d6ad08..a94011d 100644 --- a/SIGNALESP/__vm/Upload.vmps.xml +++ b/SIGNALESP/__vm/Upload.vmps.xml @@ -1,8 +1,8 @@ - + - + From ef11666e43c85076592679bc96c4d6435ebc6168 Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Tue, 22 Aug 2017 22:18:44 +0200 Subject: [PATCH 20/40] SIGNALESP.ino Corrected last commit, to also support non cc1101 version correctly --- SIGNALESP/SIGNALESP.ino | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/SIGNALESP/SIGNALESP.ino b/SIGNALESP/SIGNALESP.ino index ae62b84..9dcfb60 100644 --- a/SIGNALESP/SIGNALESP.ino +++ b/SIGNALESP/SIGNALESP.ino @@ -135,14 +135,13 @@ void setup() { #ifdef CMP_CC1101 cc1101::CCinit(); hasCC1101 = cc1101::checkCC1101(); - if (hasCC1101) { DBG_PRINTLN("CC1101 found"); musterDec.setRSSICallback(&cc1101::getRSSI); // Provide the RSSI Callback - }// else - musterDec.setRSSICallback(&rssiCallback); // Provide the RSSI Callback + } else #endif - + musterDec.setRSSICallback(&rssiCallback); // Provide the RSSI Callback + #ifdef DEBUG Serial.printf("\nTry connecting to WiFi with SSID '%s'\n", WiFi.SSID().c_str()); #endif From b272b2676a9ef5de1f9a7ff657f94a05d8285ce9 Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Thu, 24 Aug 2017 21:58:45 +0200 Subject: [PATCH 21/40] Auto relwase with travisci --- .travis.yml | 66 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/.travis.yml b/.travis.yml index 95021fd..9495af4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,38 +1,46 @@ language: c before_install: - - "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16" - - sleep 3 - - export DISPLAY=:1.0 - - wget http://downloads.arduino.cc/arduino-1.6.5-linux64.tar.xz - - tar xf arduino-1.6.5-linux64.tar.xz - - sudo mv arduino-1.6.5 /usr/local/share/arduino - - sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino +- /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile + --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16 +- sleep 3 +- export DISPLAY=:1.0 +- wget http://downloads.arduino.cc/arduino-1.6.5-linux64.tar.xz +- tar xf arduino-1.6.5-linux64.tar.xz +- sudo mv arduino-1.6.5 /usr/local/share/arduino +- sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino install: - - git clone http://github.com/tzapu/WiFiManager.git /usr/local/share/arduino/libraries/WIFIManager - #- ln -s $PWD /usr/local/share/arduino/libraries/WiFiManager -# boards manager not working on 1.6.7 - 1.6.8 - - arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json" --save-prefs -# install lib arduino json not working in 1.6.5 -# - arduino --install-library "ArduinoJson" - - git clone https://github.com/bblanchon/ArduinoJson /usr/local/share/arduino/libraries/ArduinoJson - - ln -s $PWD/src/_micro-api/libraries/bitstore /usr/local/share/arduino/libraries/bitstore - - ln -s $PWD/src/_micro-api/libraries/output /usr/local/share/arduino/libraries/output - - ln -s $PWD/src/_micro-api/libraries/signalDecoder /usr/local/share/arduino/libraries/signalDecoder - - ln -s $PWD/src/_micro-api/libraries/SimpleFIFO /usr/local/share/arduino/libraries/simpleFIFO - - ln -s $PWD/src/_micro-api/libraries/fastdelegate /usr/local/share/arduino/libraries/fastdelegate - - arduino --install-boards esp8266:esp8266 - - arduino --board esp8266:esp8266:generic --save-prefs - - arduino --pref "compiler.warning_level=all" --save-prefs +- git clone http://github.com/tzapu/WiFiManager.git /usr/local/share/arduino/libraries/WIFIManager +- arduino --pref "boardsmanager.additional.urls=http://arduino.esp8266.com/stable/package_esp8266com_index.json" + --save-prefs +- git clone https://github.com/bblanchon/ArduinoJson /usr/local/share/arduino/libraries/ArduinoJson +- ln -s $PWD/src/_micro-api/libraries/bitstore /usr/local/share/arduino/libraries/bitstore +- ln -s $PWD/src/_micro-api/libraries/output /usr/local/share/arduino/libraries/output +- ln -s $PWD/src/_micro-api/libraries/signalDecoder /usr/local/share/arduino/libraries/signalDecoder +- ln -s $PWD/src/_micro-api/libraries/SimpleFIFO /usr/local/share/arduino/libraries/simpleFIFO +- ln -s $PWD/src/_micro-api/libraries/fastdelegate /usr/local/share/arduino/libraries/fastdelegate +- mkdir $PWD/build +- arduino --install-boards esp8266:esp8266 +- arduino --board esp8266:esp8266:generic --save-prefs +- arduino --pref "compiler.warning_level=all" --save-prefs +- arduino --pref "build.path=$PWD/build" --save-prefs script: - - "ls -l /usr/local/share/arduino/libraries/" - - "file /usr/local/share/arduino/libraries/*/*" - - "echo $PWD" - - "echo $HOME" - - "ls $PWD" - - arduino -v --verbose-build --verify $PWD/SIGNALESP/SIGNALESP.ino 2>&1 +- ls -l /usr/local/share/arduino/libraries/ +- file /usr/local/share/arduino/libraries/*/* +- echo $PWD +- echo $HOME +- ls $PWD +- arduino -v --verbose-build --verify $PWD/SIGNALESP/SIGNALESP.ino 2>&1 after_success: - - bash <(curl -s https://codecov.io/bash) +- bash <(curl -s https://codecov.io/bash) notifications: email: on_success: change on_failure: change +deploy: + provider: releases + api_key: + secure: moWO4Z0OP5dzsTJMxQg40BIipaFOEdVujGEXMHaLlJ0oLOd0hBatGuyJ+RffgeTTuneIUPRwVuhR9Oj51f/Kh20D93MaL1wD/TzI4LlqhG1/fiIb7hkkZ0qsXX1/zkeUHjKm/jdptw1Pwps6UMoqG/KVRseZmr3a5BoMlaE1Cgx1pa1MUSqQq771gN+0XMV71CJv5BhoxCP0GryOOYaWtK2lXaFntOHEmwLEyOG2GcYfoafKaQ5sBqcKu/RhZ/LiovhouB5on7QI4pa7UNdJJNIIr0FZVnJkfqIXmbSDRMcyj1oa9T7LV1+8BmbTnZun7OeV6ZR36sz3rS7lnox/0lwZWQkG5js+yNXZnMZ+KFVavAPQE7NFQkQEb5GQ/mdwONQoQNYV9KtoOgN+tJwUxCjohxzYh4hv2CXJdYQbbkkVeRDrm1/82fc7A0xG0MD0az96GTCOvbCvGzmhvYbxRSpFqfHtOosPjSahaoMKiksfXlvLAM2K0xakNMl1lQThQbuZyvvvHsMLItcoZcQXEiQfztnkpIPOzfUlJL+7BqoSFAe9c3+tE/7STKkvj/5Ak2mTC+6xx3Y9gYFUtB4hQnBu5S9pR246VjMw8EqWd8d+mWrAoU7LwiZibcCuBBYjQDraiGp92CJkVfAgWarzJEMW4J47l2+RlB3/Cs5Dv9A= + file: '$PWD/build/SIGNALESP.hex' + on: + repo: RFD-FHEM/SIGNALESP + branch: dev-cc1101 From 730017a76c2676c468a5a0c458d43e52d7d042f4 Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Fri, 25 Aug 2017 21:06:06 +0200 Subject: [PATCH 22/40] Corrected lib property version --- src/_micro-api/libraries/bitstore/library.properties | 3 ++- src/_micro-api/libraries/fastdelegate/library.properties | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/_micro-api/libraries/bitstore/library.properties b/src/_micro-api/libraries/bitstore/library.properties index 7623107..f84e34e 100644 --- a/src/_micro-api/libraries/bitstore/library.properties +++ b/src/_micro-api/libraries/bitstore/library.properties @@ -1,4 +1,5 @@ -name=bitstoreversion=1.0.0 +name=bitstore +version=1.0.0 author=Visual Micro maintainer=Visual Micro sentence=bitstore library code diff --git a/src/_micro-api/libraries/fastdelegate/library.properties b/src/_micro-api/libraries/fastdelegate/library.properties index ae297cf..08cc139 100644 --- a/src/_micro-api/libraries/fastdelegate/library.properties +++ b/src/_micro-api/libraries/fastdelegate/library.properties @@ -1,4 +1,5 @@ -name=fastdelegate=1.0.0 +name=fastdelegate +version=1.0.0 author=Don Clugston, maintainer=Don Clugston sentence=fastdelegate From 48affea53f7950d002d9b7f60fbdfd513499b7c6 Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Fri, 25 Aug 2017 21:27:24 +0200 Subject: [PATCH 23/40] signalDecoder.h updated includes --- src/_micro-api/libraries/signalDecoder/src/signalDecoder.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/_micro-api/libraries/signalDecoder/src/signalDecoder.h b/src/_micro-api/libraries/signalDecoder/src/signalDecoder.h index bf8b1a6..c35eb8e 100644 --- a/src/_micro-api/libraries/signalDecoder/src/signalDecoder.h +++ b/src/_micro-api/libraries/signalDecoder/src/signalDecoder.h @@ -38,9 +38,9 @@ #endif #define DEBUG 1 -#include "output.h" -#include "bitstore.h" -#include "FastDelegate.h" +#include +#include +#include #define maxNumPattern 8 #define maxMsgSize 254 From 9936aaa000ca525ed1440b15cb7a6255bbc76a2f Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Fri, 25 Aug 2017 21:33:48 +0200 Subject: [PATCH 24/40] Updated SIGNALESP.ino to prevent compile errors --- SIGNALESP/SIGNALESP.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/SIGNALESP/SIGNALESP.ino b/SIGNALESP/SIGNALESP.ino index 9dcfb60..035fdc2 100644 --- a/SIGNALESP/SIGNALESP.ino +++ b/SIGNALESP/SIGNALESP.ino @@ -36,6 +36,7 @@ WiFiClient serverClient; SimpleFIFO FiFo; //store FIFO_LENGTH # ints #include +#include SignalDetectorClass musterDec; From 0724151f4883e5243f917b790f056dfca05d58b8 Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Fri, 25 Aug 2017 21:59:21 +0200 Subject: [PATCH 25/40] new travis config with release folder --- .travis.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9495af4..b3e0460 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,18 +18,19 @@ install: - ln -s $PWD/src/_micro-api/libraries/signalDecoder /usr/local/share/arduino/libraries/signalDecoder - ln -s $PWD/src/_micro-api/libraries/SimpleFIFO /usr/local/share/arduino/libraries/simpleFIFO - ln -s $PWD/src/_micro-api/libraries/fastdelegate /usr/local/share/arduino/libraries/fastdelegate -- mkdir $PWD/build +- mkdir $PWD/release - arduino --install-boards esp8266:esp8266 - arduino --board esp8266:esp8266:generic --save-prefs - arduino --pref "compiler.warning_level=all" --save-prefs -- arduino --pref "build.path=$PWD/build" --save-prefs +- arduino --pref "build.path=$PWD/release" --save-prefs script: - ls -l /usr/local/share/arduino/libraries/ -- file /usr/local/share/arduino/libraries/*/* +- - echo $PWD - echo $HOME - ls $PWD - arduino -v --verbose-build --verify $PWD/SIGNALESP/SIGNALESP.ino 2>&1 +- file $PWD/* after_success: - bash <(curl -s https://codecov.io/bash) notifications: @@ -40,7 +41,7 @@ deploy: provider: releases api_key: secure: moWO4Z0OP5dzsTJMxQg40BIipaFOEdVujGEXMHaLlJ0oLOd0hBatGuyJ+RffgeTTuneIUPRwVuhR9Oj51f/Kh20D93MaL1wD/TzI4LlqhG1/fiIb7hkkZ0qsXX1/zkeUHjKm/jdptw1Pwps6UMoqG/KVRseZmr3a5BoMlaE1Cgx1pa1MUSqQq771gN+0XMV71CJv5BhoxCP0GryOOYaWtK2lXaFntOHEmwLEyOG2GcYfoafKaQ5sBqcKu/RhZ/LiovhouB5on7QI4pa7UNdJJNIIr0FZVnJkfqIXmbSDRMcyj1oa9T7LV1+8BmbTnZun7OeV6ZR36sz3rS7lnox/0lwZWQkG5js+yNXZnMZ+KFVavAPQE7NFQkQEb5GQ/mdwONQoQNYV9KtoOgN+tJwUxCjohxzYh4hv2CXJdYQbbkkVeRDrm1/82fc7A0xG0MD0az96GTCOvbCvGzmhvYbxRSpFqfHtOosPjSahaoMKiksfXlvLAM2K0xakNMl1lQThQbuZyvvvHsMLItcoZcQXEiQfztnkpIPOzfUlJL+7BqoSFAe9c3+tE/7STKkvj/5Ak2mTC+6xx3Y9gYFUtB4hQnBu5S9pR246VjMw8EqWd8d+mWrAoU7LwiZibcCuBBYjQDraiGp92CJkVfAgWarzJEMW4J47l2+RlB3/Cs5Dv9A= - file: '$PWD/build/SIGNALESP.hex' + file: '$PWD/release/SIGNALESP.hex' on: repo: RFD-FHEM/SIGNALESP branch: dev-cc1101 From 920e6e93923246f988ee6ae8b26259e2ca34703d Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Fri, 25 Aug 2017 22:02:56 +0200 Subject: [PATCH 26/40] updated travis config --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b3e0460..d4cade7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ script: - echo $HOME - ls $PWD - arduino -v --verbose-build --verify $PWD/SIGNALESP/SIGNALESP.ino 2>&1 -- file $PWD/* +- file $PWD/release/* after_success: - bash <(curl -s https://codecov.io/bash) notifications: @@ -41,7 +41,7 @@ deploy: provider: releases api_key: secure: moWO4Z0OP5dzsTJMxQg40BIipaFOEdVujGEXMHaLlJ0oLOd0hBatGuyJ+RffgeTTuneIUPRwVuhR9Oj51f/Kh20D93MaL1wD/TzI4LlqhG1/fiIb7hkkZ0qsXX1/zkeUHjKm/jdptw1Pwps6UMoqG/KVRseZmr3a5BoMlaE1Cgx1pa1MUSqQq771gN+0XMV71CJv5BhoxCP0GryOOYaWtK2lXaFntOHEmwLEyOG2GcYfoafKaQ5sBqcKu/RhZ/LiovhouB5on7QI4pa7UNdJJNIIr0FZVnJkfqIXmbSDRMcyj1oa9T7LV1+8BmbTnZun7OeV6ZR36sz3rS7lnox/0lwZWQkG5js+yNXZnMZ+KFVavAPQE7NFQkQEb5GQ/mdwONQoQNYV9KtoOgN+tJwUxCjohxzYh4hv2CXJdYQbbkkVeRDrm1/82fc7A0xG0MD0az96GTCOvbCvGzmhvYbxRSpFqfHtOosPjSahaoMKiksfXlvLAM2K0xakNMl1lQThQbuZyvvvHsMLItcoZcQXEiQfztnkpIPOzfUlJL+7BqoSFAe9c3+tE/7STKkvj/5Ak2mTC+6xx3Y9gYFUtB4hQnBu5S9pR246VjMw8EqWd8d+mWrAoU7LwiZibcCuBBYjQDraiGp92CJkVfAgWarzJEMW4J47l2+RlB3/Cs5Dv9A= - file: '$PWD/release/SIGNALESP.hex' + file: '$PWD/release/SIGNALESP.ino.hex' on: repo: RFD-FHEM/SIGNALESP branch: dev-cc1101 From 411f02e89ce9959ab82b4b7150adcb1108aa0235 Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Fri, 25 Aug 2017 22:14:17 +0200 Subject: [PATCH 27/40] upload SIGNALESP.cpp.bin after travis build --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d4cade7..868a74a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -41,7 +41,7 @@ deploy: provider: releases api_key: secure: moWO4Z0OP5dzsTJMxQg40BIipaFOEdVujGEXMHaLlJ0oLOd0hBatGuyJ+RffgeTTuneIUPRwVuhR9Oj51f/Kh20D93MaL1wD/TzI4LlqhG1/fiIb7hkkZ0qsXX1/zkeUHjKm/jdptw1Pwps6UMoqG/KVRseZmr3a5BoMlaE1Cgx1pa1MUSqQq771gN+0XMV71CJv5BhoxCP0GryOOYaWtK2lXaFntOHEmwLEyOG2GcYfoafKaQ5sBqcKu/RhZ/LiovhouB5on7QI4pa7UNdJJNIIr0FZVnJkfqIXmbSDRMcyj1oa9T7LV1+8BmbTnZun7OeV6ZR36sz3rS7lnox/0lwZWQkG5js+yNXZnMZ+KFVavAPQE7NFQkQEb5GQ/mdwONQoQNYV9KtoOgN+tJwUxCjohxzYh4hv2CXJdYQbbkkVeRDrm1/82fc7A0xG0MD0az96GTCOvbCvGzmhvYbxRSpFqfHtOosPjSahaoMKiksfXlvLAM2K0xakNMl1lQThQbuZyvvvHsMLItcoZcQXEiQfztnkpIPOzfUlJL+7BqoSFAe9c3+tE/7STKkvj/5Ak2mTC+6xx3Y9gYFUtB4hQnBu5S9pR246VjMw8EqWd8d+mWrAoU7LwiZibcCuBBYjQDraiGp92CJkVfAgWarzJEMW4J47l2+RlB3/Cs5Dv9A= - file: '$PWD/release/SIGNALESP.ino.hex' + file: '$PWD/release/SIGNALESP.cpp.bin' on: repo: RFD-FHEM/SIGNALESP branch: dev-cc1101 From 2141a84f79dbc87c928fd9238dae825f764dcc02 Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Fri, 25 Aug 2017 22:24:46 +0200 Subject: [PATCH 28/40] travis prevent cleanup after build --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 868a74a..f0da0db 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,6 +38,7 @@ notifications: on_success: change on_failure: change deploy: + skip_cleanup: true provider: releases api_key: secure: moWO4Z0OP5dzsTJMxQg40BIipaFOEdVujGEXMHaLlJ0oLOd0hBatGuyJ+RffgeTTuneIUPRwVuhR9Oj51f/Kh20D93MaL1wD/TzI4LlqhG1/fiIb7hkkZ0qsXX1/zkeUHjKm/jdptw1Pwps6UMoqG/KVRseZmr3a5BoMlaE1Cgx1pa1MUSqQq771gN+0XMV71CJv5BhoxCP0GryOOYaWtK2lXaFntOHEmwLEyOG2GcYfoafKaQ5sBqcKu/RhZ/LiovhouB5on7QI4pa7UNdJJNIIr0FZVnJkfqIXmbSDRMcyj1oa9T7LV1+8BmbTnZun7OeV6ZR36sz3rS7lnox/0lwZWQkG5js+yNXZnMZ+KFVavAPQE7NFQkQEb5GQ/mdwONQoQNYV9KtoOgN+tJwUxCjohxzYh4hv2CXJdYQbbkkVeRDrm1/82fc7A0xG0MD0az96GTCOvbCvGzmhvYbxRSpFqfHtOosPjSahaoMKiksfXlvLAM2K0xakNMl1lQThQbuZyvvvHsMLItcoZcQXEiQfztnkpIPOzfUlJL+7BqoSFAe9c3+tE/7STKkvj/5Ak2mTC+6xx3Y9gYFUtB4hQnBu5S9pR246VjMw8EqWd8d+mWrAoU7LwiZibcCuBBYjQDraiGp92CJkVfAgWarzJEMW4J47l2+RlB3/Cs5Dv9A= From 1e99d8a88e30a41221b90008a25a32ecf2793051 Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Fri, 25 Aug 2017 22:35:38 +0200 Subject: [PATCH 29/40] Updated travis to Arduino IDE version 1.6.13 --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index f0da0db..4210588 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,9 +4,9 @@ before_install: --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16 - sleep 3 - export DISPLAY=:1.0 -- wget http://downloads.arduino.cc/arduino-1.6.5-linux64.tar.xz -- tar xf arduino-1.6.5-linux64.tar.xz -- sudo mv arduino-1.6.5 /usr/local/share/arduino +- wget http://downloads.arduino.cc/arduino-1.6.13-linux64.tar.xz +- tar xf arduino-1.6.13-linux64.tar.xz +- sudo mv arduino-1.6.13 /usr/local/share/arduino - sudo ln -s /usr/local/share/arduino/arduino /usr/local/bin/arduino install: - git clone http://github.com/tzapu/WiFiManager.git /usr/local/share/arduino/libraries/WIFIManager From 1564a993eb0bdeae08d07cea517cf41518e8128d Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Fri, 25 Aug 2017 22:42:19 +0200 Subject: [PATCH 30/40] Upload changed to SIGNALESP.bin --- .travis.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4210588..99d4c24 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,7 +32,9 @@ script: - arduino -v --verbose-build --verify $PWD/SIGNALESP/SIGNALESP.ino 2>&1 - file $PWD/release/* after_success: -- bash <(curl -s https://codecov.io/bash) +#- bash <(curl -s https://codecov.io/bash) +- file $PWD/release/* +- mv $PWD/release/SIGNALESP.ino.bin $PWD/release/SIGNALESP.bin notifications: email: on_success: change @@ -42,7 +44,7 @@ deploy: provider: releases api_key: secure: moWO4Z0OP5dzsTJMxQg40BIipaFOEdVujGEXMHaLlJ0oLOd0hBatGuyJ+RffgeTTuneIUPRwVuhR9Oj51f/Kh20D93MaL1wD/TzI4LlqhG1/fiIb7hkkZ0qsXX1/zkeUHjKm/jdptw1Pwps6UMoqG/KVRseZmr3a5BoMlaE1Cgx1pa1MUSqQq771gN+0XMV71CJv5BhoxCP0GryOOYaWtK2lXaFntOHEmwLEyOG2GcYfoafKaQ5sBqcKu/RhZ/LiovhouB5on7QI4pa7UNdJJNIIr0FZVnJkfqIXmbSDRMcyj1oa9T7LV1+8BmbTnZun7OeV6ZR36sz3rS7lnox/0lwZWQkG5js+yNXZnMZ+KFVavAPQE7NFQkQEb5GQ/mdwONQoQNYV9KtoOgN+tJwUxCjohxzYh4hv2CXJdYQbbkkVeRDrm1/82fc7A0xG0MD0az96GTCOvbCvGzmhvYbxRSpFqfHtOosPjSahaoMKiksfXlvLAM2K0xakNMl1lQThQbuZyvvvHsMLItcoZcQXEiQfztnkpIPOzfUlJL+7BqoSFAe9c3+tE/7STKkvj/5Ak2mTC+6xx3Y9gYFUtB4hQnBu5S9pR246VjMw8EqWd8d+mWrAoU7LwiZibcCuBBYjQDraiGp92CJkVfAgWarzJEMW4J47l2+RlB3/Cs5Dv9A= - file: '$PWD/release/SIGNALESP.cpp.bin' + file: '$PWD/release/SIGNALESP.bin' on: repo: RFD-FHEM/SIGNALESP branch: dev-cc1101 From bc8ee143fd98a81dddefde2579c81957da8e8223 Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Fri, 25 Aug 2017 22:54:09 +0200 Subject: [PATCH 31/40] travis deploy only with tags --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 99d4c24..e53de27 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,4 +47,5 @@ deploy: file: '$PWD/release/SIGNALESP.bin' on: repo: RFD-FHEM/SIGNALESP + tags: true branch: dev-cc1101 From dd36c0c1fee619773558468f0205f7c029b6fa2e Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Fri, 25 Aug 2017 23:07:03 +0200 Subject: [PATCH 32/40] Compile only, whenn tagged with commit --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index e53de27..91e6dbf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,4 +48,5 @@ deploy: on: repo: RFD-FHEM/SIGNALESP tags: true + condition: "$TRAVIS_TAG =~ ^release.*$" branch: dev-cc1101 From 2ca07dd4e9833d018415259eb95c134ca0772480 Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Mon, 28 Aug 2017 23:12:00 +0200 Subject: [PATCH 33/40] quick hack to output in signaldecoderclass via ethernet server. #7 also removed some unused code and reworked yield() usage in lib --- SIGNALESP/__vm/Compile.vmps.xml | 2 +- SIGNALESP/__vm/Configuration.Release.vmps.xml | 2 +- SIGNALESP/__vm/Upload.vmps.xml | 2 +- .../signalDecoder/src/signalDecoder.cpp | 45 +++++-------------- .../signalDecoder/src/signalDecoder.h | 2 + 5 files changed, 15 insertions(+), 38 deletions(-) diff --git a/SIGNALESP/__vm/Compile.vmps.xml b/SIGNALESP/__vm/Compile.vmps.xml index a94011d..94689ad 100644 --- a/SIGNALESP/__vm/Compile.vmps.xml +++ b/SIGNALESP/__vm/Compile.vmps.xml @@ -2,7 +2,7 @@ - + diff --git a/SIGNALESP/__vm/Configuration.Release.vmps.xml b/SIGNALESP/__vm/Configuration.Release.vmps.xml index 36cd4c1..2429df0 100644 --- a/SIGNALESP/__vm/Configuration.Release.vmps.xml +++ b/SIGNALESP/__vm/Configuration.Release.vmps.xml @@ -2,7 +2,7 @@ - + diff --git a/SIGNALESP/__vm/Upload.vmps.xml b/SIGNALESP/__vm/Upload.vmps.xml index a94011d..94689ad 100644 --- a/SIGNALESP/__vm/Upload.vmps.xml +++ b/SIGNALESP/__vm/Upload.vmps.xml @@ -2,7 +2,7 @@ - + diff --git a/src/_micro-api/libraries/signalDecoder/src/signalDecoder.cpp b/src/_micro-api/libraries/signalDecoder/src/signalDecoder.cpp index e9fc8e1..87e78bc 100644 --- a/src/_micro-api/libraries/signalDecoder/src/signalDecoder.cpp +++ b/src/_micro-api/libraries/signalDecoder/src/signalDecoder.cpp @@ -97,7 +97,6 @@ inline void SignalDetectorClass::doDetect() //if (messageLen == 0) valid = true; if (!valid) { // Try output - yield(); processMessage(); if (messageLen < minMessageLen) { MsMoveCount = 3; @@ -186,7 +185,6 @@ void SignalDetectorClass::compress_pattern() { if (histo[idx] == 0) continue; - yield(); for (uint8_t idx2 = idx + 1; idx2> 15) @@ -328,6 +326,7 @@ void SignalDetectorClass::processMessage() MSG_WRITE(patternLow); MSG_WRITE(highByte(patternInt) | B10000000); MSG_PRINT(SERIAL_DELIMITER); + yield(); } uint8_t n; @@ -367,6 +366,8 @@ void SignalDetectorClass::processMessage() { MSG_PRINT(message[i]); } + + yield(); MSG_PRINT(SERIAL_DELIMITER); MSG_PRINT("CP="); MSG_PRINT(clock); MSG_PRINT(SERIAL_DELIMITER); // ClockPulse MSG_PRINT("SP="); MSG_PRINT(sync); MSG_PRINT(SERIAL_DELIMITER); // SyncPulse @@ -391,25 +392,6 @@ void SignalDetectorClass::processMessage() MSG_PRINT("\n"); success = true; -#ifdef mp_crc - const int8_t crco = printMsgRaw(mstart, mend, &preamble, &postamble); - - if ((mend < messageLen - minMessageLen) && (message[mend + 1] == message[mend - mstart + mend + 1])) { - mstart = mend + 1; - byte crcs = 0x00; -#ifndef ARDUSIM - for (uint8_t i = mstart + 1; i <= mend - mstart + mend; i++) - { - crcs = _crc_ibutton_update(crcs, message[i]); - } -#endif - if (crcs == crco) - { - // repeat found - } - //processMessage(); // Todo: needs to be optimized - } -#endif } @@ -752,7 +734,6 @@ void SignalDetectorClass::calcHisto(const uint8_t startpos, uint8_t endpos) { histo[i] = 0; } - yield(); if (endpos == 0) endpos = messageLen; /*for (uint8_t i = startpos; i < endpos; i++) @@ -763,7 +744,6 @@ void SignalDetectorClass::calcHisto(const uint8_t startpos, uint8_t endpos) uint8_t bval; for (uint8_t i = bstartpos; i> 4]++; histo[bval & B00001111]++; @@ -822,7 +802,6 @@ bool SignalDetectorClass::getSync() if (state == clockfound) // we need a clock to find this type of sync { - yield(); // clock wurde bereits durch getclock bestimmt. for (int8_t p = patternLen - 1; p >= 0; --p) // Schleife fuer langen Syncpuls { @@ -889,35 +868,30 @@ bool SignalDetectorClass::getSync() return false; } +/* void SignalDetectorClass::printMsgStr(const String * first, const String * second, const String * third) { MSG_PRINT(*first); MSG_PRINT(*second); MSG_PRINT(*third); - } - +*/ +/* int8_t SignalDetectorClass::printMsgRaw(uint8_t m_start, const uint8_t m_end, const String * preamble, const String * postamble) { MSG_PRINT(*preamble); //String msg; //msg.reserve(m_end-mstart); - byte crcv = 0x00; for (; m_start <= m_end; m_start++) { //msg + =message[m_start]; //MSG_PRINT((100*message[m_start])+(10*message[m_start])+message[m_start]); MSG_PRINT(message[m_start]); -#ifndef ARDUSIM - //crcv = _crc_ibutton_update(crcv, message[m_start]); -#endif } - //MSG_PRINT(msg); MSG_PRINT(*postamble); - return crcv; - //printMsgStr(preamble,&msg,postamble);} + yield(); } - +*/ @@ -1057,6 +1031,7 @@ void ManchesterpatternDecoder::printMessageHexStr() sprintf(hexStr, "%01X", getMCByte(idx) & 0xF); MSG_PRINT(hexStr); } + yield(); } @@ -1086,6 +1061,7 @@ void ManchesterpatternDecoder::printMessagePulseStr() MSG_PRINT("LH="); MSG_PRINT(pdec->pattern[longhigh]); MSG_PRINT(SERIAL_DELIMITER); MSG_PRINT("SL="); MSG_PRINT(pdec->pattern[shortlow]); MSG_PRINT(SERIAL_DELIMITER); MSG_PRINT("SH="); MSG_PRINT(pdec->pattern[shorthigh]); MSG_PRINT(SERIAL_DELIMITER); + yield(); } /** @brief (one liner) @@ -1451,7 +1427,6 @@ const bool ManchesterpatternDecoder::isManchester() for (uint8_t i = 0; ipattern[sortedPattern[i]] <= 0) continue; #if DEBUGDETECT >= 2 DBG_PRINT("CLK="); DBG_PRINT(sortedPattern[i]); DBG_PRINT(":"); diff --git a/src/_micro-api/libraries/signalDecoder/src/signalDecoder.h b/src/_micro-api/libraries/signalDecoder/src/signalDecoder.h index c35eb8e..12476b7 100644 --- a/src/_micro-api/libraries/signalDecoder/src/signalDecoder.h +++ b/src/_micro-api/libraries/signalDecoder/src/signalDecoder.h @@ -38,6 +38,8 @@ #endif #define DEBUG 1 +#define ETHERNET_PRINT // Quick hack to enable ethernet output in signalDecoder Lib + #include #include #include From 91d334b04198e5186bae7c96b8b28c09d23a61de Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Mon, 28 Aug 2017 23:12:54 +0200 Subject: [PATCH 34/40] SIGNALESP.ino Removed some yield() to call it not to often. --- SIGNALESP/SIGNALESP.ino | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/SIGNALESP/SIGNALESP.ino b/SIGNALESP/SIGNALESP.ino index 035fdc2..072da9a 100644 --- a/SIGNALESP/SIGNALESP.ino +++ b/SIGNALESP/SIGNALESP.ino @@ -247,15 +247,14 @@ void loop() { if (!command_available) { cmdstring = ""; } blinkLED = true; } - yield(); if (fifousage < FiFo.count()) fifousage = FiFo.count(); - while (FiFo.count()>0) { //Puffer auslesen und an Dekoder uebergeben + while (FiFo.count()>0) { //Puffer auslesen und an Dekoder uebergeben aktVal = FiFo.dequeue(); state = musterDec.decode(&aktVal); if (state) blinkLED = true; //LED blinken, wenn Meldung dekodiert - yield(); + if (FiFo.count()<120) yield(); } } @@ -830,14 +829,12 @@ void storeFunctions(const int8_t ms, int8_t mu, int8_t mc) mu = mu << 1; mc = mc << 2; int8_t dat = ms | mu | mc; - yield(); EEPROM.write(addr_features, dat); } void getFunctions(bool *ms, bool *mu, bool *mc) { int8_t dat = EEPROM.read(addr_features); - yield(); *ms = bool(dat &(1 << 0)); *mu = bool(dat &(1 << 1)); *mc = bool(dat &(1 << 2)); @@ -856,7 +853,6 @@ void dumpEEPROM() { void initEEPROM() { EEPROM.begin(512); //Max bytes of eeprom to use - yield(); if (EEPROM.read(EE_MAGIC_OFFSET) == VERSION_1 && EEPROM.read(EE_MAGIC_OFFSET + 1) == VERSION_2) { DBG_PRINTLN("Reading values fom eeprom"); From 9289653500c612a6a52139a3a2297501ffb9eec3 Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Mon, 28 Aug 2017 23:21:49 +0200 Subject: [PATCH 35/40] output tag in travis build --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 91e6dbf..e358adf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,6 +35,7 @@ after_success: #- bash <(curl -s https://codecov.io/bash) - file $PWD/release/* - mv $PWD/release/SIGNALESP.ino.bin $PWD/release/SIGNALESP.bin +- echo $TRAVIS_TAG notifications: email: on_success: change From a5678247b36e7d9d24c5e3207dbbf478a8d4d155 Mon Sep 17 00:00:00 2001 From: sidey79 <7968127+sidey79@users.noreply.github.com> Date: Fri, 1 Sep 2017 22:13:57 +0200 Subject: [PATCH 36/40] Removed yield() after MSG_PRINT, because esp_yield is already included in the esp write function --- src/_micro-api/libraries/signalDecoder/src/signalDecoder.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/_micro-api/libraries/signalDecoder/src/signalDecoder.cpp b/src/_micro-api/libraries/signalDecoder/src/signalDecoder.cpp index 87e78bc..0ba1677 100644 --- a/src/_micro-api/libraries/signalDecoder/src/signalDecoder.cpp +++ b/src/_micro-api/libraries/signalDecoder/src/signalDecoder.cpp @@ -326,7 +326,6 @@ void SignalDetectorClass::processMessage() MSG_WRITE(patternLow); MSG_WRITE(highByte(patternInt) | B10000000); MSG_PRINT(SERIAL_DELIMITER); - yield(); } uint8_t n; @@ -367,7 +366,6 @@ void SignalDetectorClass::processMessage() MSG_PRINT(message[i]); } - yield(); MSG_PRINT(SERIAL_DELIMITER); MSG_PRINT("CP="); MSG_PRINT(clock); MSG_PRINT(SERIAL_DELIMITER); // ClockPulse MSG_PRINT("SP="); MSG_PRINT(sync); MSG_PRINT(SERIAL_DELIMITER); // SyncPulse @@ -1031,7 +1029,6 @@ void ManchesterpatternDecoder::printMessageHexStr() sprintf(hexStr, "%01X", getMCByte(idx) & 0xF); MSG_PRINT(hexStr); } - yield(); } @@ -1061,7 +1058,6 @@ void ManchesterpatternDecoder::printMessagePulseStr() MSG_PRINT("LH="); MSG_PRINT(pdec->pattern[longhigh]); MSG_PRINT(SERIAL_DELIMITER); MSG_PRINT("SL="); MSG_PRINT(pdec->pattern[shortlow]); MSG_PRINT(SERIAL_DELIMITER); MSG_PRINT("SH="); MSG_PRINT(pdec->pattern[shorthigh]); MSG_PRINT(SERIAL_DELIMITER); - yield(); } /** @brief (one liner) From 133d3ee0b085043c0f14a50bbec2a527ff06b3d9 Mon Sep 17 00:00:00 2001 From: habeIchVergessen Date: Thu, 24 Aug 2017 18:07:39 +0200 Subject: [PATCH 37/40] bugfix ccconf --- SIGNALESP/SIGNALESP.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SIGNALESP/SIGNALESP.ino b/SIGNALESP/SIGNALESP.ino index 072da9a..8c484d3 100644 --- a/SIGNALESP/SIGNALESP.ino +++ b/SIGNALESP/SIGNALESP.ino @@ -606,7 +606,7 @@ void HandleCommand() else if (cmdstring.charAt(1) == 'S') { configSET(); } -#ifdef comp_cc1101 +#ifdef CMP_CC1101 else if (isHexadecimalDigit(cmdstring.charAt(1)) && isHexadecimalDigit(cmdstring.charAt(2)) && hasCC1101) { reg = cmdstringPos2int(1); cc1101::readCCreg(reg); @@ -616,7 +616,7 @@ void HandleCommand() MSG_PRINTLN(F("Unsupported command")); } } -#ifdef comp_cc1101 +#ifdef CMP_CC1101 else if (cmdstring.charAt(0) == cmd_write) { // write EEPROM und CC11001 register if (cmdstring.charAt(1) == 'S' && cmdstring.charAt(2) == '3' && hasCC1101) { // WS Command Strobes cc1101::commandStrobes(); From 47635a43ebb4c96286ece4c16ce79dea8ab33a21 Mon Sep 17 00:00:00 2001 From: habeIchVergessen Date: Wed, 30 Aug 2017 21:53:49 +0200 Subject: [PATCH 38/40] bugfix ccconf (write EEPROM fixed) # Conflicts: # SIGNALESP/SIGNALESP.ino # src/_micro-api/libraries/signalDecoder/src/signalDecoder.cpp --- SIGNALESP/SIGNALESP.ino | 16 ++++++++++---- SIGNALESP/cc1101.h | 21 +++++++++++++++++++ .../signalDecoder/src/signalDecoder.cpp | 12 +++++------ 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/SIGNALESP/SIGNALESP.ino b/SIGNALESP/SIGNALESP.ino index 8c484d3..110d4b0 100644 --- a/SIGNALESP/SIGNALESP.ino +++ b/SIGNALESP/SIGNALESP.ino @@ -18,6 +18,7 @@ #define BAUDRATE 115200 #define FIFO_LENGTH 200 #define DEBUG 1 +#define _CC1101_DEBUG_CONFIG #define ETHERNET_PRINT @@ -137,7 +138,7 @@ void setup() { cc1101::CCinit(); hasCC1101 = cc1101::checkCC1101(); if (hasCC1101) { - DBG_PRINTLN("CC1101 found"); + DBG_PRINTLN("CC1101 found (rev. 0" + String(cc1101::getRevision(), HEX) + ")"); musterDec.setRSSICallback(&cc1101::getRSSI); // Provide the RSSI Callback } else #endif @@ -247,6 +248,7 @@ void loop() { if (!command_available) { cmdstring = ""; } blinkLED = true; } + if (fifousage < FiFo.count()) fifousage = FiFo.count(); @@ -552,7 +554,7 @@ void HandleCommand() if (hasCC1101) { MSG_PRINT(F("cc1101")); switch(cc1101::chipVersion()) { -// case 0x08: // CC1101_VERSION 0x31 + case 0x08: // CC1101_VERSION 0x31 case 0x18: // CC1101_VERSION 0xF1 MSG_PRINT(F(" 433MHz")); break; @@ -560,6 +562,9 @@ void HandleCommand() case 0x14: // CC1101_VERSION 0xF1 MSG_PRINT(F(" 868MHz")); break; + default: + MSG_PRINT(" chip unknown 0x" + String(cc1101::chipVersion(), HEX)); + break; } } #endif @@ -624,7 +629,8 @@ void HandleCommand() else if (isHexadecimalDigit(cmdstring.charAt(1)) && isHexadecimalDigit(cmdstring.charAt(2)) && isHexadecimalDigit(cmdstring.charAt(3)) && isHexadecimalDigit(cmdstring.charAt(4))) { reg = cmdstringPos2int(1); val = cmdstringPos2int(3); - EEPROM.write(reg, val); + EEPROM.write(reg+1, val); // scheinbar hat sich hier etwas um 1 Byte verschoben + EEPROM.commit(); if (hasCC1101) { cc1101::writeCCreg(reg, val); } @@ -660,6 +666,7 @@ void HandleCommand() } else if (cmdstring.charAt(0) == cmd_ccFactoryReset && hasCC1101) { cc1101::ccFactoryReset(); + EEPROM.commit(); cc1101::CCinit(); } #endif @@ -745,7 +752,8 @@ inline void ethernetEvent() if (!serverClient || !serverClient.connected()) { if (serverClient) serverClient.stop(); serverClient = Server.available(); - DBG_PRINTLN("New client: "); + DBG_PRINT("New client: "); + DBG_PRINTLN(serverClient.remoteIP()); return; } //no free/disconnected spot so reject diff --git a/SIGNALESP/cc1101.h b/SIGNALESP/cc1101.h index 5684084..cefe42b 100644 --- a/SIGNALESP/cc1101.h +++ b/SIGNALESP/cc1101.h @@ -188,6 +188,11 @@ namespace cc1101 { 0x00, // 28 RCCTRL0 }; + // prototypes +#ifdef _CC1101_DEBUG_CONFIG + void dumpConfigRegister(); +#endif + byte hex2int(byte hex) { // convert a hexdigit to int // Todo: printf oder scanf nutzen if (hex >= '0' && hex <= '9') hex = hex - '0'; else if (hex >= 'a' && hex <= 'f') hex = hex - 'a' + 10; @@ -386,6 +391,7 @@ namespace cc1101 { EEPROM.write(EE_CC1100_PA + i, 0); } } + EEPROM.commit(); MSG_PRINTLN("ccFactoryReset done"); } @@ -491,6 +497,9 @@ namespace cc1101 { DBG_PRINTLN("POR Done"); delay(10); +#ifdef _CC1101_DEBUG_CONFIG + dumpConfigRegister(); +#endif cc1101_Select(); sendSPI(CC1100_WRITE_BURST); @@ -506,6 +515,18 @@ namespace cc1101 { setReceiveMode(); } +#ifdef _CC1101_DEBUG_CONFIG + void dumpConfigRegister() { + Serial.printf("\ndump config register:\n"); + for (byte i=0; i<0x28; i++) { + Serial.printf("%02X ", readReg(i, CC1101_CONFIG)); + if (i % 16 == 15) + Serial.printf("\n"); + } + Serial.printf("\n"); + } +#endif + bool regCheck() { diff --git a/src/_micro-api/libraries/signalDecoder/src/signalDecoder.cpp b/src/_micro-api/libraries/signalDecoder/src/signalDecoder.cpp index 0ba1677..c314535 100644 --- a/src/_micro-api/libraries/signalDecoder/src/signalDecoder.cpp +++ b/src/_micro-api/libraries/signalDecoder/src/signalDecoder.cpp @@ -105,7 +105,8 @@ inline void SignalDetectorClass::doDetect() } else if (messageLen == minMessageLen) { state = detecting; // Set state to detecting, because we have more than minMessageLen data gathered, so this is no noise - rssiValue = _rssiCallback(); + if (_rssiCallback != NULL) // don't call uninitialized function pointer + rssiValue = _rssiCallback(); } int8_t fidx = findpatt(*first); @@ -338,7 +339,7 @@ void SignalDetectorClass::processMessage() } if ((mstart & 1) == 1) { // ungerade mstart--; - (message.getByte(mstart / 2, &n) & 15) | 128; // high nibble = 8 als Kennzeichen für ungeraden mstart + (message.getByte(mstart / 2, &n) & 15) | 128; // high nibble = 8 als Kennzeichen für ungeraden mstart MSG_WRITE(n); mstart += 2; } @@ -610,7 +611,7 @@ void SignalDetectorClass::processMessage() #endif } } - if (!m_truncated) // Todo: Eventuell auf vollen Puffer prüfen + if (!m_truncated) // Todo: Eventuell auf vollen Puffer prüfen { reset(); } @@ -792,7 +793,7 @@ bool SignalDetectorClass::getClock() bool SignalDetectorClass::getSync() { - // Durchsuchen aller Musterpulse und prueft ob darin ein Sync Faktor enthalten ist. Anschließend wird verifiziert ob dieser Syncpuls auch im Signal nacheinander uebertragen wurde + // Durchsuchen aller Musterpulse und prueft ob darin ein Sync Faktor enthalten ist. Anschließend wird verifiziert ob dieser Syncpuls auch im Signal nacheinander uebertragen wurde // #if DEBUGDETECT > 3 DBG_PRINTLN(" -- Searching Sync -- "); @@ -1270,7 +1271,7 @@ const bool ManchesterpatternDecoder::doDecode() { #endif //pdec->printOut(); - pdec->bufferMove(i); // Todo: BufferMove könnte in die Serielle Ausgabe verschoben werden, das würde ein paar Mikrosekunden Zeit sparen + pdec->bufferMove(i); // Todo: BufferMove könnte in die Serielle Ausgabe verschoben werden, das würde ein paar Mikrosekunden Zeit sparen //pdec->m_truncated = true; // Flag that we truncated the message array and want to receiver some more data mc_start_found = false; // This will break serval unit tests. Normaly setting this to false shoud be done by reset, needs to be checked if reset shoud be called after hex string is printed out @@ -1316,7 +1317,6 @@ const bool ManchesterpatternDecoder::doDecode() { } //MSG_PRINT(" S MC "); i++; - yield(); } pdec->mend = i - (ht ? 0 : 1); // keep short in buffer; From 17e18fde39c8c06d7dd7d0909a7ba43af137d59b Mon Sep 17 00:00:00 2001 From: habeIchVergessen Date: Sun, 3 Sep 2017 22:43:32 +0200 Subject: [PATCH 39/40] signalDecoder - remove yield() # Conflicts: # SIGNALESP/SIGNALESP.ino --- SIGNALESP/SIGNALESP.ino | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/SIGNALESP/SIGNALESP.ino b/SIGNALESP/SIGNALESP.ino index 110d4b0..fa3fdb4 100644 --- a/SIGNALESP/SIGNALESP.ino +++ b/SIGNALESP/SIGNALESP.ino @@ -18,7 +18,10 @@ #define BAUDRATE 115200 #define FIFO_LENGTH 200 #define DEBUG 1 -#define _CC1101_DEBUG_CONFIG + + + + #define ETHERNET_PRINT @@ -140,9 +143,8 @@ void setup() { if (hasCC1101) { DBG_PRINTLN("CC1101 found (rev. 0" + String(cc1101::getRevision(), HEX) + ")"); musterDec.setRSSICallback(&cc1101::getRSSI); // Provide the RSSI Callback - } else -#endif - musterDec.setRSSICallback(&rssiCallback); // Provide the RSSI Callback + } +#endif #ifdef DEBUG Serial.printf("\nTry connecting to WiFi with SSID '%s'\n", WiFi.SSID().c_str()); @@ -214,12 +216,12 @@ void setup() { os_timer_setfn(&cronTimer, cronjob, NULL); os_timer_arm(&cronTimer, 31, true); -#ifdef comp_cc1101 +#ifdef CMP_CC1101 if (!hasCC1101 || cc1101::regCheck()) { #endif enableReceive(); DBG_PRINTLN(F("receiver enabled")); -#ifdef comp_cc1101 +#ifdef CMP_CC1101 } else { DBG_PRINTLN(F("cc1101 is not correctly set. Please do a factory reset via command e")); } @@ -760,7 +762,7 @@ inline void ethernetEvent() // WiFiClient newClient = Server.available(); // newClient.stop(); } - yield(); +// yield(); } void serialEvent() From 21606b205062162591694e6e19be15053f6e4768 Mon Sep 17 00:00:00 2001 From: habeIchVergessen Date: Tue, 22 Aug 2017 12:40:06 +0200 Subject: [PATCH 40/40] hardware revision (cherry picked from commit 8c36432968b0f33f6a67e152f8998909bebeb45d) # Conflicts: # SIGNALESP/SIGNALESP.ino # SIGNALESP/cc1101.h --- SIGNALESP/SIGNALESP.ino | 4 +++ SIGNALESP/cc1101.h | 68 +++++++++++++++++++++++------------------ 2 files changed, 42 insertions(+), 30 deletions(-) diff --git a/SIGNALESP/SIGNALESP.ino b/SIGNALESP/SIGNALESP.ino index fa3fdb4..3f07030 100644 --- a/SIGNALESP/SIGNALESP.ino +++ b/SIGNALESP/SIGNALESP.ino @@ -128,6 +128,10 @@ void setup() { Serial.println("\n\n"); +#ifdef DEBUG + Serial.println("SPI: MOSI " + String(MOSI) + ", MISO " + String(MISO) + ", SCK " + String(SCK) + ", CS " + String(SS)); +#endif + pinMode(PIN_RECEIVE, INPUT); pinMode(PIN_LED, OUTPUT); diff --git a/SIGNALESP/cc1101.h b/SIGNALESP/cc1101.h index cefe42b..67cbe51 100644 --- a/SIGNALESP/cc1101.h +++ b/SIGNALESP/cc1101.h @@ -48,11 +48,18 @@ namespace cc1101 { #define CC1100_IOCFG2 0x00 // GDO2 output configuration #define CC1100_PKTCTRL0 0x08 // Packet config register - // Status registers - older version base on 0x30 - #define CC1101_PARTNUM 0xF0 // Chip ID - #define CC1101_VERSION 0xF1 // Chip ID - #define CC1100_RSSI 0xF4 // Received signal strength indication - #define CC1100_MARCSTATE 0xF5 // Control state machine state + uint8_t revision = 0x01; + + // Status registers - newer version base on 0xF0 + #define CC1101_PARTNUM_REV01 0xF0 // Chip ID + #define CC1101_VERSION_REV01 0xF1 // Chip ID + #define CC1100_RSSI_REV01 0xF4 // Received signal strength indication + #define CC1100_MARCSTATE_REV01 0xF5 // Control state machine state + // Status registers - older version base on 0x30 + #define CC1101_PARTNUM_REV00 0x30 // Chip ID + #define CC1101_VERSION_REV00 0x31 // Chip ID + #define CC1100_RSSI_REV00 0x34 // Received signal strength indication + #define CC1100_MARCSTATE_REV00 0x35 // Control state machine state // Strobe commands #define CC1101_SRES 0x30 // reset @@ -188,11 +195,8 @@ namespace cc1101 { 0x00, // 28 RCCTRL0 }; - // prototypes -#ifdef _CC1101_DEBUG_CONFIG - void dumpConfigRegister(); -#endif - + + byte hex2int(byte hex) { // convert a hexdigit to int // Todo: printf oder scanf nutzen if (hex >= '0' && hex <= '9') hex = hex - '0'; else if (hex >= 'a' && hex <= 'f') hex = hex - 'a' + 10; @@ -391,15 +395,30 @@ namespace cc1101 { EEPROM.write(EE_CC1100_PA + i, 0); } } - EEPROM.commit(); + EEPROM.commit(); MSG_PRINTLN("ccFactoryReset done"); } - uint8_t chipVersion() { return readReg(CC1101_VERSION, CC1101_READ_SINGLE); }; + uint8_t chipVersionRev() + { + return readReg((revision == 0x01 ? CC1101_VERSION_REV01 : CC1101_VERSION_REV00), CC1101_READ_SINGLE); + }; + + uint8_t chipVersion() { + uint8_t version = chipVersionRev(); + + if (revision != 0x00 && (version == 0xFF || version == 0x00)) { + revision = 0x00; + version = chipVersionRev(); + } + + return version; + } + bool checkCC1101() { - uint8_t partnum = readReg(CC1101_PARTNUM, CC1101_READ_SINGLE); // Partnum uint8_t version = chipVersion(); // Version + uint8_t partnum = readReg((revision == 0x01 ? CC1101_PARTNUM_REV01 : CC1101_PARTNUM_REV00), CC1101_READ_SINGLE); // Partnum DBG_PRINT("CCVersion="); DBG_PRINTLN("0x" + String(version, HEX)); DBG_PRINT("CCPartnum="); DBG_PRINTLN("0x" + String(partnum, HEX)); @@ -444,9 +463,10 @@ namespace cc1101 { pinAsOutput(PIN_SEND); // gdo0Pi, sicherheitshalber bis zum CC1101 init erstmal input } + uint8_t getRevision() { return revision; } uint8_t getRSSI() { - return readReg(CC1100_RSSI, CC1101_STATUS);// Pruefen ob Umwandung von uint to int den richtigen Wert zurueck gibt + return readReg((revision == 0x01 ? CC1100_RSSI_REV01 : CC1100_RSSI_REV00), CC1101_STATUS);// Pruefen ob Umwandung von uint to int den richtigen Wert zurueck gibt } inline void setIdleMode() @@ -456,7 +476,7 @@ namespace cc1101 { } uint8_t currentMode() { - return readReg(CC1100_MARCSTATE, CC1100_READ_BURST); + return readReg((revision == 0x01 ? CC1100_MARCSTATE_REV01 : CC1100_MARCSTATE_REV00), CC1100_READ_BURST); } void setReceiveMode() @@ -497,9 +517,7 @@ namespace cc1101 { DBG_PRINTLN("POR Done"); delay(10); -#ifdef _CC1101_DEBUG_CONFIG - dumpConfigRegister(); -#endif + cc1101_Select(); sendSPI(CC1100_WRITE_BURST); @@ -515,18 +533,8 @@ namespace cc1101 { setReceiveMode(); } -#ifdef _CC1101_DEBUG_CONFIG - void dumpConfigRegister() { - Serial.printf("\ndump config register:\n"); - for (byte i=0; i<0x28; i++) { - Serial.printf("%02X ", readReg(i, CC1101_CONFIG)); - if (i % 16 == 15) - Serial.printf("\n"); - } - Serial.printf("\n"); - } -#endif - + + bool regCheck() {