From bcd835aca69b635052fe9627c46b89429e2964fe Mon Sep 17 00:00:00 2001 From: Carl Klemm Date: Tue, 5 May 2020 22:20:00 +0200 Subject: [PATCH] Support multi backend items --- CMakeLists.txt | 2 +- W433DataTransmitter.cpp | 98 +++++++++++++++++++++++++++++++++ W433DataTransmitter.h | 30 ++++++++++ WirelessRelay.cpp | 62 +++++---------------- WirelessRelay.h | 24 +++----- item.cpp | 9 +++ item.h | 14 +++++ main.cpp | 118 +++++++++++++++++++++------------------- uvositem.cpp | 24 ++++++++ uvositem.h | 16 ++++++ 10 files changed, 276 insertions(+), 121 deletions(-) create mode 100644 W433DataTransmitter.cpp create mode 100644 W433DataTransmitter.h create mode 100644 item.cpp create mode 100644 item.h create mode 100644 uvositem.cpp create mode 100644 uvositem.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8bd4cc7..0c15d93 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,7 @@ set(COMPILE_FLAGS "" CACHE STRING "Additional Compiler Flags") # Set own source files # Simply list all your C / C++ source (not header!) files here -set(SRC_FILES main.cpp serial.cpp WirelessRelay.cpp pwm.cpp rgbled.cpp W433DataReciver.cpp) +set(SRC_FILES main.cpp serial.cpp WirelessRelay.cpp pwm.cpp rgbled.cpp W433DataReciver.cpp W433DataTransmitter.cpp uvositem.cpp item.cpp) # Compiler suite specification set(CMAKE_C_COMPILER /usr/bin/avr-gcc) diff --git a/W433DataTransmitter.cpp b/W433DataTransmitter.cpp new file mode 100644 index 0000000..62906b4 --- /dev/null +++ b/W433DataTransmitter.cpp @@ -0,0 +1,98 @@ +#include "W433DataTransmitter.h" +#include "writepin.h" + +W433DataTransmitter::W433DataTransmitter(volatile unsigned char *port, const unsigned char pin): _port(port), _pin(pin) +{ +} + +void W433DataTransmitter::sendBit(const bool bit) +{ + switch(bit) + { + case true: + writePin(_port,_pin,true); + _delay_us(SMALL_TIME); + writePin(_port,_pin,false); + _delay_us(LARGE_TIME); + writePin(_port,_pin,true); + _delay_us(SMALL_TIME); + writePin(_port,_pin,false); + _delay_us(LARGE_TIME); + break; + + case false: + writePin(_port,_pin,true); + _delay_us(LARGE_TIME); + writePin(_port,_pin,false); + _delay_us(SMALL_TIME); + writePin(_port,_pin,true); + _delay_us(SMALL_TIME); + writePin(_port,_pin,false); + _delay_us(LARGE_TIME); + break; + } +} + +void W433DataTransmitter::sendSyncpulse() +{ + for(uint8_t i = 0; i < 25; ++i) + { + writePin(_port,_pin,true); + _delay_us(SYNC_TIME); + writePin(_port,_pin,false); + _delay_us(SYNC_TIME); + } +} + +void W433DataTransmitter::sendEndPulse() +{ + writePin(_port,_pin,false); + _delay_us(LARGE_TIME); + writePin(_port,_pin,true); + _delay_us(LARGE_TIME); + writePin(_port,_pin,false); + _delay_us(LARGE_TIME*10); +} + +void W433DataTransmitter::sendRawData(const uint8_t data) +{ + for(uint8_t i = 0; i < 8; i++) sendBit(data & ( 1 << (7 - i))); +} + +void W433DataTransmitter::sendPacket(const uint32_t data) +{ + sendSyncpulse(); + _delay_us(LARGE_TIME); + sendRawData(signature); + uint8_t checksum = 0; + for(uint8_t i = 0; i < 4; ++i) + { + uint8_t dataOctet = (data & (0xFF000000 >> i*8 )) >> (24 - 8*i); + //for(uint8_t i = 0; i < 8; i++) checksum = checksum + (dataOctet & ( 1 << (8 - i))); + for(uint8_t i = 0; i < 8; i++) checksum = checksum + ((dataOctet & ( 1 << (8 - i))) >> (8 - i)); + sendRawData( dataOctet ); + + } + sendRawData( checksum ); + sendEndPulse(); +} + +void W433DataTransmitter::send(const uint8_t* const data, uint16_t length) +{ + uint16_t packets = length/4; + if(length % 4 != 0) ++packets; + for(uint8_t j = 0; j < packets; j++) + { + uint32_t paketData = 0; + uint8_t* paketDataPointer = reinterpret_cast(&paketData); + for(uint8_t i = 0; i < 4 && j*4+i < length; i++) paketDataPointer[3-i] = data[j*4+i]; + sendPacket(paketData); + } +} + +void W433DataTransmitter::send(const uint8_t data) +{ + sendPacket(data); +} + + diff --git a/W433DataTransmitter.h b/W433DataTransmitter.h new file mode 100644 index 0000000..007f8a2 --- /dev/null +++ b/W433DataTransmitter.h @@ -0,0 +1,30 @@ +#pragma once +#include + +#include + + +class W433DataTransmitter +{ +private: + + static constexpr uint16_t LARGE_TIME = 2000; + static constexpr uint16_t SMALL_TIME = 500; + static constexpr uint16_t SYNC_TIME = 800; + + static constexpr uint8_t signature = 0xA5; + volatile unsigned char * const _port; + const unsigned char _pin; + + void sendBit(const bool bit); + void sendSyncpulse(); + void sendRawData(const uint8_t data); + void sendEndPulse(); + +public: + + W433DataTransmitter(volatile unsigned char * const port, const unsigned char pin); + void send(const uint8_t* const data, uint16_t length); + void send(const uint8_t data); + void sendPacket(const uint32_t data); +}; diff --git a/WirelessRelay.cpp b/WirelessRelay.cpp index c835211..78df162 100644 --- a/WirelessRelay.cpp +++ b/WirelessRelay.cpp @@ -14,7 +14,7 @@ void WirelessRelay::sendId() for(short i = 0; i<10; i++) { - sendBit( _id & 1 << (15 - i) ); + sendBit( id & 1 << (15 - i) ); } } @@ -54,64 +54,32 @@ void WirelessRelay::sync() _delay_us(SMALL_TIME*31); } -void WirelessRelay::on() +void WirelessRelay::setValue(const uint8_t value) { - _state = true; + lastValue = value; for(short z = 0; z<10; z++) { sendId(); - sendBit(true); - sendBit(false); + sendBit(value); + sendBit(!value); sync(); } } -void WirelessRelay::off() -{ - _state = false; - for(short z = 0; z<10; z++) - { - sendId(); - sendBit(false); - sendBit(true); - sync(); - } -} - -uint16_t WirelessRelay::getId() -{ - return _id; -} - -bool WirelessRelay::getExpectedState() -{ - return _state; -} - -char* WirelessRelay::getName() -{ - return _name; -} - -void WirelessRelay::setName(char name[]) -{ - memcpy(_name, name, strlen(name)+1); -} - -void WirelessRelay::init( const uint16_t id, char nameIn[]) -{ - setName(nameIn); - _id=id; -} - void WirelessRelay::resend() { - _state ? on() : off(); + setValue(lastValue); } -WirelessRelay::WirelessRelay(const uint16_t id, char nameIn[]) +WirelessRelay::WirelessRelay(const uint16_t idIn, char nameIn[]) { - init(id, nameIn); + id = idIn; + setName(nameIn); + type = 0; } -WirelessRelay::WirelessRelay(){} +WirelessRelay::WirelessRelay(const Item& item) +{ + Item::operator=(item); + type = 0; +} diff --git a/WirelessRelay.h b/WirelessRelay.h index c26a19e..7306fd0 100644 --- a/WirelessRelay.h +++ b/WirelessRelay.h @@ -3,8 +3,9 @@ #include #include"writepin.h" +#include "item.h" -class WirelessRelay +class WirelessRelay: public Item { public: static constexpr uint16_t LARGE_TIME = 750; @@ -13,23 +14,14 @@ public: static constexpr uint16_t MAX_NAME_LENGTH = 16; private: - bool _state = false; - uint16_t _id; - char _name[MAX_NAME_LENGTH]; - void sendBit(const bool i); - void sync(); - void sendId(); + void sendBit(const bool i); + void sync(); + void sendId(); public: - WirelessRelay(const uint16_t id, char nameIn[]); - WirelessRelay(); - void init(const uint16_t id, char nameIn[]); - void on(); - void off(); - char* getName(); - void setName(char* name); - uint16_t getId(); - bool getExpectedState(); + WirelessRelay(const uint16_t idIn, char nameIn[]); + WirelessRelay(const Item& item); + void setValue(const uint8_t value); void resend(); }; #endif diff --git a/item.cpp b/item.cpp new file mode 100644 index 0000000..837b685 --- /dev/null +++ b/item.cpp @@ -0,0 +1,9 @@ +#include "item.h" +#include "string.h" + +void Item::setName(const char * const nameN) +{ + size_t len = strlen(name); + if(len < MAX_NAME_LENGTH)memcpy(name, nameN, len+1); +} + diff --git a/item.h b/item.h new file mode 100644 index 0000000..0197de5 --- /dev/null +++ b/item.h @@ -0,0 +1,14 @@ +#pragma once +#include + +class Item +{ +public: + static constexpr uint16_t MAX_NAME_LENGTH = 16; + bool lastValue = 0; + uint16_t id; + char name[MAX_NAME_LENGTH]=""; + uint8_t type = 0; + + void setName(const char * const name); +}; diff --git a/main.cpp b/main.cpp index 8875b28..9174e66 100644 --- a/main.cpp +++ b/main.cpp @@ -12,16 +12,18 @@ #include "watchdog.h" #include "staticvector.h" #include "W433DataReciver.h" +#include "W433DataTransmitter.h" +#include "uvositem.h" #define COMMAND_BUFFER_SIZE 64 #define SNPRINTF_BUFFER_SIZE 96 -#define MAX_RELAYS 32 -#define RELAY_VECTOR_EEPROM_ADDR 32 +#define MAX_ITEMS 24 +#define ITEM_VECTOR_EEPROM_ADDR 32 char buffer[SNPRINTF_BUFFER_SIZE]; -SVector relays; +SVector items; bool sensorsPaused = false; @@ -48,10 +50,10 @@ inline static void printHelp(Serial* serial) serial->write_p(PSTR("Available Commands: \n\ help : Show this prompt.\n\ - relay add [id] [name] : Add Wireless Relay. Save to make permant.\n\ - relay delete [n] : Delete n'th Relay. Save to make permant.\n\ - relay [on/off] [nn] : Turn on/off nth relay.\n\ - relay resend [on/off] : Turn on/off periodic auto resend. Save to make permant.\n\ + item add [id] [type] [name]: Add Wireless item. Save to make permant.\n\ + item delete [n] : Delete n'th item. Save to make permant.\n\ + item [on/off] [nn] : Turn on/off nth relay.\n\ + item resend [on/off] : Turn on/off periodic auto resend. Save to make permant.\n\ save : Save current state as startup state.\n\ load : load startup state.\n\ state : Get machine readable state.\n\ @@ -80,7 +82,7 @@ int freeRAM() void save() { EEPROM_write_char(4, resendEnabled); - EEPROM_write_class< SVector > (RELAY_VECTOR_EEPROM_ADDR, relays); + EEPROM_write_class< SVector > (ITEM_VECTOR_EEPROM_ADDR, items); } void loadRGB(RgbLed* rgbled) @@ -91,58 +93,56 @@ void loadRGB(RgbLed* rgbled) void load() { resendEnabled = EEPROM_read_char(4); - EEPROM_read_class< SVector > (RELAY_VECTOR_EEPROM_ADDR, &relays); + EEPROM_read_class< SVector > (ITEM_VECTOR_EEPROM_ADDR, &items); } -void writeRelayState(Serial* serial, WirelessRelay* relay, uint8_t number) +void writeItemState(Serial* serial, Item* relay, uint8_t number) { - uint16_t id = relay->getId(); - snprintf(buffer, SNPRINTF_BUFFER_SIZE, "RELAY NUMBER: %u ID: %s%s%s STATE: %u NAME: %s\n", number, + const uint16_t id = relay->id; + snprintf(buffer, SNPRINTF_BUFFER_SIZE, "ITEM NUMBER: %u ID: %s%s%s%s TYPE: %u STATE: %u NAME: %s\n", number, bit_rep[ id >> 12], bit_rep[(id & 0x0F00) >> 8 ], bit_rep[(id & 0x00F0) >> 4 ], - relay->getExpectedState(), - relay->getName() + bit_rep[(id & 0x000F)], + relay->type, + relay->lastValue, + relay->name ); serial->write(buffer, SNPRINTF_BUFFER_SIZE); } -void relayDispatch(SVector* relays, Pwm16b* auxPwm, char* token, Serial* serial) +void itemDispatch(SVector* items, Pwm16b* auxPwm, char* token, Serial* serial) { if( strcmp(token, "add") == 0 ) { token = strtok(NULL, " \n"); uint16_t id = strtol(token, nullptr, 2 ); - if(id != 0 && relays->remainingCapacity() > 0) + token = strtok(NULL, " \n"); + uint8_t type = strtol(token, nullptr, 10 ); + if(id != 0 && (type == 0 || type == 1) && items->remainingCapacity() > 0) { id = id << 4; token = strtok(NULL, "\0"); - if( token == NULL ) - { - char name[] = ""; - WirelessRelay relay(id, name); - relays->push_back(relay); - } - else - { - WirelessRelay relay(id, token); - relays->push_back(relay); - } - writeRelayState(serial, &relays->back(), relays->count()-1); + Item item; + item.id = id; + item.type = type; + if( token != NULL ) item.setName(token); + items->push_back(item); + writeItemState(serial, &items->back(), items->count()-1); } - else if(relays->remainingCapacity() == 0) serial->write_p(PSTR("Relay storage full.\n")); - else serial->write_p(PSTR("Usage: relay add [id] [name]\n [id] being a 16bit binary nummber and [name] an optional string\n")); + else if(items->remainingCapacity() == 0) serial->write_p(PSTR("Relay storage full.\n")); + else serial->write_p(PSTR("Usage: item add [id] [type] [name]\n [id] being a 16bit binary nummber and [name] an optional string\n")); } else if( strcmp(token, "delete") == 0 ) { token = strtok(NULL, " \n"); - if(relays->count() > 0) + if(items->count() > 0) { - uint16_t index = relays->count(); + uint16_t index = items->count(); if( token != NULL) index = atoi(token); - snprintf(buffer, SNPRINTF_BUFFER_SIZE, "Deleting relay NUMBER: %u NAME: %s\n", index, relays->at(index).getName()); + snprintf(buffer, SNPRINTF_BUFFER_SIZE, "Deleting item NUMBER: %u NAME: %s\n", index, items->at(index).name); serial->write(buffer, SNPRINTF_BUFFER_SIZE); - relays->erase(index); + items->erase(index); } } else if( strcmp(token, "on") == 0 ) @@ -151,15 +151,16 @@ void relayDispatch(SVector* relays, Pwm16b* auxPwm, c if( token != NULL) { uint8_t selected = strtol(token, nullptr, 10); - if (selected < relays->count()) + if (selected < items->count()) { - relays->at(selected).on(); + if(items->at(selected).type == 0)WirelessRelay(items->at(selected)).setValue(true); + else UvosItem(items->at(selected)).setValue(true); - writeRelayState(serial, &relays->at(selected), selected); + writeItemState(serial, &items->at(selected), selected); } - else serial->write_p(PSTR("No sutch Relay\n")); + else serial->write_p(PSTR("No sutch item\n")); } - else serial->write_p(PSTR("Usage: relay on [nn]\n")); + else serial->write_p(PSTR("Usage: item on [nn]\n")); } else if( strcmp(token, "off") == 0 ) { @@ -167,15 +168,16 @@ void relayDispatch(SVector* relays, Pwm16b* auxPwm, c if( token != NULL) { uint8_t selected = strtol(token, nullptr, 10); - if (selected < relays->count()) + if (selected < items->count()) { - relays->at(selected).off(); + if(items->at(selected).type == 0)WirelessRelay(items->at(selected)).setValue(false); + else UvosItem(items->at(selected)).setValue(false); - writeRelayState(serial, &relays->at(selected), selected); + writeItemState(serial, &items->at(selected), selected); } - else serial->write_p(PSTR("No sutch Relay\n")); + else serial->write_p(PSTR("No sutch item\n")); } - else serial->write_p(PSTR("Usage: relay off [nn]\n")); + else serial->write_p(PSTR("Usage: item off [nn]\n")); } else if( strcmp(token, "resend") == 0 ) { @@ -192,7 +194,7 @@ void relayDispatch(SVector* relays, Pwm16b* auxPwm, c else { serial->write(token); - serial->write_p(PSTR(" is not a valid subcommand: relay [add/delete/on/off]\n")); + serial->write_p(PSTR(" is not a valid subcommand: item [add/delete/on/off]\n")); } } @@ -202,7 +204,7 @@ void rgbDispatch(RgbLed* rgbled, char* token, Serial* serial) { rgbled->on(); serial->write_p(PSTR("RGB lights on\n")); - }s + } else if( strcmp(token, "off") == 0 ) { rgbled->off(); @@ -297,7 +299,7 @@ void auxDispatch(Pwm16b* auxPwm, char* token, Serial* serial) } } -void serialDispatch(Serial* serial, SVector* relays, RgbLed* rgbled, Pwm16b* auxPwm, W433DataReciver* reciver) +void serialDispatch(Serial* serial, SVector* items, RgbLed* rgbled, Pwm16b* auxPwm, W433DataReciver* reciver) { if(serial->dataIsWaiting()) @@ -308,10 +310,10 @@ void serialDispatch(Serial* serial, SVector* relays, { setBit(&PCICR, PCIE1, false); char* token = strtok(buffer, " \n"); - if(strcmp(token, "relay") == 0) + if(strcmp(token, "item") == 0) { reciver->waitForReciveIdle(); - relayDispatch(relays, auxPwm, strtok(NULL, " \n"), serial); + itemDispatch(items, auxPwm, strtok(NULL, " \n"), serial); } else if(strcmp(token, "rgb") == 0) { @@ -333,11 +335,10 @@ void serialDispatch(Serial* serial, SVector* relays, } else if(strcmp(token, "state") == 0) { - serial->write_p(PSTR("Relays:\n")); - for(uint8_t i = 0; i < relays->count(); i++) + serial->write_p(PSTR("Items:\n")); + for(uint8_t i = 0; i < items->count(); i++) { - writeRelayState(serial, &relays->at(i), i); - //serial->putChar('\n'); + writeItemState(serial, &items->at(i), i); } serial->write_p(PSTR("EOL\n")); } @@ -449,14 +450,17 @@ int main() setBit(&PCICR, PCIE1, true); setBit(&PCMSK1, PCINT8, true); W433DataReciver reciver(&PINC, PC0, &TCNT1, &TIFR1, &sensorPacketRecived, reinterpret_cast(&serial), &reciverError); + W433DataTransmitter transmitter(&PORTB, PB5); + UvosItem::transmitter=&transmitter; + - serial.write_p(PSTR("RGBController v1.1 starting\n")); + serial.write_p(PSTR("RGBController v1.5 starting\n")); load(); while(true) { - serialDispatch(&serial, &relays, &rgbled, &pwmTc1, &reciver); + serialDispatch(&serial, &items, &rgbled, &pwmTc1, &reciver); rgbled.logic(); if(doorOne != readPin(&PINB, PB3) && !sensorsPaused) @@ -494,10 +498,10 @@ int main() if(resendNow) { - for(uint16_t i = 0; i < relays.count(); i++) + for(uint16_t i = 0; i < items.count(); i++) { reciver.waitForReciveIdle(); - relays[i].resend(); + items[i].type == 0 ? WirelessRelay(items[i]).resend() : UvosItem(items[i]).resend(); _delay_ms(100); } resendNow = false; diff --git a/uvositem.cpp b/uvositem.cpp new file mode 100644 index 0000000..17ede7f --- /dev/null +++ b/uvositem.cpp @@ -0,0 +1,24 @@ +#include "uvositem.h" + +UvosItem::UvosItem(const uint8_t idIn, char nameIn[]) +{ + id = 129 << 8 + idIn; + type = 1; +} + +UvosItem::UvosItem(const Item& item) +{ + Item::operator=(item); + type = 1; +} + +void UvosItem::setValue(const uint8_t value) +{ + const uint8_t paket[4] = {id >> 8, id & 0x00FF, 0, value}; + if(transmitter)transmitter->send(paket, 4); +} + +void UvosItem::resend() +{ + setValue(lastValue); +} diff --git a/uvositem.h b/uvositem.h new file mode 100644 index 0000000..8c005ef --- /dev/null +++ b/uvositem.h @@ -0,0 +1,16 @@ +#pragma once + +#include "item.h" +#include "W433DataTransmitter.h" + +class UvosItem: public Item +{ +public: + inline static W433DataTransmitter* transmitter = nullptr; + +public: + UvosItem(const uint8_t idIn, char nameIn[]); + UvosItem(const Item& item); + void setValue(const uint8_t value); + void resend(); +};