Introduced advertisement on channel 1 and clock-channel to be configurable.
This commit is contained in:
@@ -13,6 +13,13 @@
|
||||
#define NETWORK_ADDRESS_MASTER_SEND "1ClkM"
|
||||
#define NETWORK_ADDRESS_MASTER_RECEIVE "2ClkM"
|
||||
|
||||
#define DEFAULT_TIME_BETWEEN_CLOCK_ADVERTISEMENTS_ms 60000
|
||||
#define DEFAULT_TIME_BETWEEN_PAIRING_OFFERINGS_ms 33000
|
||||
#define DEFAULT_TIME_FOR_CLIENTS_TO_RESPOND_ms 20
|
||||
#define MIN_TIME_BETWEEN_TRANSMISSIONS_ms 2
|
||||
#define ADVERTISEMENT_CHANNEL 1
|
||||
#define DEFAULT_CLOCK_CHANNEL 11
|
||||
|
||||
// relay based clock control behaviour
|
||||
#define DEFAULT_HOLD_RELAY_MS 150
|
||||
#define DEFAULT_MIN_RELAY_OFF_TIME_MS 80
|
||||
|
15
src/main.cpp
15
src/main.cpp
@@ -28,6 +28,9 @@ char static_ip[16] = "10.0.1.56";
|
||||
char static_gw[16] = "10.0.1.1";
|
||||
char static_sn[16] = "255.255.255.0";
|
||||
|
||||
char clockName[MAX_CLOCK_NAME_LEN] = "fastclk";
|
||||
uint8_t clockChannel = DEFAULT_CLOCK_CHANNEL;
|
||||
|
||||
//flag for saving data
|
||||
bool shouldSaveConfig = false;
|
||||
|
||||
@@ -207,6 +210,9 @@ void setup() {
|
||||
|
||||
// setupWifiConnection();
|
||||
|
||||
|
||||
radio.setClockChannel(clockChannel);
|
||||
radio.setClockName(clockName);
|
||||
radio.begin();
|
||||
fastclock.begin();
|
||||
pinMode(POWER_OFF_PIN, INPUT);
|
||||
@@ -236,7 +242,7 @@ void checkForPowerOffRequest() {
|
||||
}
|
||||
}
|
||||
|
||||
bool requestToRegisterSent = false;
|
||||
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
@@ -244,12 +250,6 @@ void loop(void)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!requestToRegisterSent) {
|
||||
radio.broadcastOfferPairing("testClock", nRF_Channel);
|
||||
requestToRegisterSent = true;
|
||||
return;
|
||||
}
|
||||
|
||||
checkForPowerOffRequest();
|
||||
|
||||
#if defined(AUTOSTART_CLOCK_AFTER_ms)
|
||||
@@ -267,6 +267,7 @@ void loop(void)
|
||||
#endif
|
||||
|
||||
fastclock.loop();
|
||||
radio.loop();
|
||||
display.showDashboard();
|
||||
|
||||
}
|
||||
|
187
src/radio.cpp
187
src/radio.cpp
@@ -12,8 +12,6 @@ static int sendFailedCounter = 0;
|
||||
static unsigned long stopTime = 0, pauseTime = 0;
|
||||
static char thisClockName[MAX_CLOCK_NAME_LEN];
|
||||
|
||||
static bool inTX=1, inRX=0, role=inRX;
|
||||
|
||||
#define MAX_CLIENTS_MANAGED 20
|
||||
static uint8_t numberOfKnownClients = 0;
|
||||
static struct {
|
||||
@@ -22,6 +20,23 @@ static struct {
|
||||
} client[MAX_CLIENTS_MANAGED];
|
||||
static uint8_t nextClientNetworkAddress = 1;
|
||||
|
||||
void Radio::switchToSenderRole(void)
|
||||
{
|
||||
Serial.println("*** changing to Tx role");
|
||||
rf24.openWritingPipe(addresses[1]);
|
||||
rf24.openReadingPipe(1,addresses[0]);
|
||||
rf24.stopListening();
|
||||
role = inTX; // Become the primary transmitter (ping out)
|
||||
}
|
||||
|
||||
void Radio::switchToReceiverRole(void)
|
||||
{
|
||||
Serial.println("*** changing to Rx role");
|
||||
rf24.openWritingPipe(addresses[0]);
|
||||
rf24.openReadingPipe(1,addresses[1]);
|
||||
rf24.startListening();
|
||||
role = inRX; // Become the primary receiver (pong back)
|
||||
}
|
||||
|
||||
void Radio::begin(void) {
|
||||
display->addLogMessage("Start RF24 radio");
|
||||
@@ -31,7 +46,7 @@ void Radio::begin(void) {
|
||||
rf24.begin();
|
||||
if (rf24.isChipConnected()) { display->addLogMessage("*** RF chip found"); }
|
||||
else { display->addLogMessage("*** ERROR: RF chip not found!"); }
|
||||
rf24.setChannel(1);
|
||||
rf24.setChannel(clockChannel);
|
||||
rf24.setPALevel(RF24_PA_MAX);
|
||||
rf24.setDataRate(RF24_2MBPS);
|
||||
rf24.setAutoAck(0);
|
||||
@@ -50,64 +65,77 @@ void Radio::begin(void) {
|
||||
if (rf24.testCarrier() || rf24.testRPD()) { display->addLogMessage("*** Carrier/RPD seen on radio"); }
|
||||
if (rf24.failureDetected) { display->addLogMessage("*** Radio error detected!"); }
|
||||
|
||||
|
||||
#if 0
|
||||
// Open a writing and reading pipe on each radio, with opposite addresses
|
||||
if (isMaster){
|
||||
rf24.openWritingPipe(addresses[1]);
|
||||
rf24.openReadingPipe(1,addresses[0]);
|
||||
} else {
|
||||
rf24.openWritingPipe(addresses[0]);
|
||||
rf24.openReadingPipe(1,addresses[1]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Start the radio listening for data
|
||||
rf24.startListening();
|
||||
//rf24.startListening();
|
||||
switchToReceiverRole();
|
||||
}
|
||||
|
||||
static void switchToSenderRole(RF24 radio)
|
||||
{
|
||||
Serial.println("*** master: CHANGING TO TRANSMIT ROLE");
|
||||
radio.openWritingPipe(addresses[1]);
|
||||
radio.openReadingPipe(1,addresses[0]);
|
||||
radio.stopListening();
|
||||
role = inTX; // Become the primary transmitter (ping out)
|
||||
}
|
||||
|
||||
static void switchToReceiverRole(RF24 radio)
|
||||
{
|
||||
Serial.println("*** master: CHANGING TO RECEIVER ROLE");
|
||||
radio.openWritingPipe(addresses[0]);
|
||||
radio.openReadingPipe(1,addresses[1]);
|
||||
radio.startListening();
|
||||
role = inRX; // Become the primary receiver (pong back)
|
||||
void Radio::broadcastMessageOnChannel(void *msg, int len, uint8_t channel) {
|
||||
Serial.print("# set channel "); Serial.println(channel);
|
||||
rf24.setChannel(channel);
|
||||
broadcastMessage(msg, len);
|
||||
Serial.print("# set channel "); Serial.println(clockChannel);
|
||||
rf24.setChannel(clockChannel); // switch back
|
||||
Serial.println("# done");
|
||||
}
|
||||
|
||||
void Radio::broadcastMessage(void *msg, int len) {
|
||||
switchToSenderRole(rf24);
|
||||
uint8_t *m = (uint8_t *) msg;
|
||||
Serial.print("*** Tx: ts="); Serial.print(millis());
|
||||
Serial.print(", len="); Serial.print(len);
|
||||
Serial.print(", typ=");
|
||||
Serial.print((uint8_t) m[0], HEX); Serial.print(" ("); Serial.print((char) m[0]);
|
||||
Serial.print("), to="); Serial.print((uint8_t) m[1], HEX);
|
||||
Serial.print(", from="); Serial.print((uint8_t) m[2], HEX);
|
||||
Serial.print(", msg="); Serial.print((uint8_t) m[3], HEX);
|
||||
Serial.print(", "); Serial.print((uint8_t) m[4], HEX);
|
||||
Serial.print(", "); Serial.print((uint8_t) m[5], HEX);
|
||||
Serial.print(", "); Serial.print((uint8_t) m[6], HEX);
|
||||
Serial.print(", "); Serial.print((uint8_t) m[7], HEX);
|
||||
Serial.print(", "); Serial.println((uint8_t) m[8], HEX);
|
||||
switchToSenderRole();
|
||||
Serial.print("#1");
|
||||
if (!rf24.writeFast(msg, len, true /*multicast*/)) {
|
||||
sendFailedCounter++;
|
||||
Serial.print("*** ERROR: failed to send msg type=");
|
||||
Serial.print(*((char *) msg));
|
||||
Serial.print(" for to=0x");
|
||||
Serial.println(*((uint8_t *) (msg+1)), HEX);
|
||||
Serial.println(m[1], HEX);
|
||||
}
|
||||
Serial.print("ts="); Serial.println(millis());
|
||||
//This is only required when NO ACK ( enableAutoAck(0) ) payloads are used
|
||||
if (millis() - pauseTime > 3) {
|
||||
pauseTime = millis();
|
||||
rf24.txStandBy(); // Need to drop out of TX mode every 4ms if sending a steady stream of multicast data
|
||||
Serial.print("pauseTime="); Serial.println(pauseTime);
|
||||
//rf24.txStandBy(); // Need to drop out of TX mode every 4ms if sending a steady stream of multicast data
|
||||
//delayMicroseconds(130); // This gives the PLL time to sync back up
|
||||
}
|
||||
stopTime = millis();
|
||||
Serial.print("stopTime="); Serial.println(stopTime);
|
||||
//This should be called to wait for completion and put the radio in standby mode after transmission, returns 0 if data still in FIFO (timed out), 1 if success
|
||||
if (!rf24.txStandBy()) { sendFailedCounter += 3; } //Standby, block only until FIFO empty or auto-retry timeout. Flush TX FIFO if failed
|
||||
//if (!rf24.txStandBy()) { sendFailedCounter += 3; } //Standby, block only until FIFO empty or auto-retry timeout. Flush TX FIFO if failed
|
||||
//radio.txStandBy(1000); //Standby, using extended timeout period of 1 second
|
||||
|
||||
Serial.print("*** send finished, fail-counter="); Serial.println(sendFailedCounter);
|
||||
Serial.print("*** send finished, failed="); Serial.println(sendFailedCounter);
|
||||
listenOnlyFor_ms(MIN_TIME_BETWEEN_TRANSMISSIONS_ms);
|
||||
}
|
||||
|
||||
void Radio::broadcastClockAdvertisement(const char *clockName, uint8_t channel) {
|
||||
struct offerPairing_s msg;
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.msgType = msgType_OfferPairing;
|
||||
msg.from = MESSAGE_FROM_Master;
|
||||
msg.to = MESSAGE_TO_ALL;
|
||||
strncpy(msg.clockName, clockName, MAX_CLOCK_NAME_LEN);
|
||||
strncpy(thisClockName, clockName, MAX_CLOCK_NAME_LEN);
|
||||
msg.channel = channel;
|
||||
int msgLength = sizeof(msg);
|
||||
|
||||
broadcastMessageOnChannel(&msg, msgLength, ADVERTISEMENT_CHANNEL);
|
||||
}
|
||||
|
||||
// send pairing offering on advertisement channel
|
||||
void Radio::broadcastOfferPairing(const char *clockName, uint8_t channel) {
|
||||
struct offerPairing_s msg;
|
||||
|
||||
@@ -170,14 +198,14 @@ void Radio::ackPairingRequest(char *clientName, uint8_t clientNetworkAddress) {
|
||||
|
||||
// handle received messages
|
||||
void Radio::handleRequestPairing(struct requestPairing_s *request) {
|
||||
int i;
|
||||
int i=0;
|
||||
bool found;
|
||||
|
||||
if (strncmp(&request->clientName[0], thisClockName, MAX_CLOCK_NAME_LEN) == 0) {
|
||||
// add this client to client list
|
||||
Serial.print("*** Rcv'd pairing request for "); Serial.println(&request->clientName[0]);
|
||||
found = false;
|
||||
for (int i=0; i<numberOfKnownClients && !found; ++i) {
|
||||
for (i=0; i<numberOfKnownClients && !found; ++i) {
|
||||
if (strncmp(&client[i].clientName[0], &request->clientName[0], MAX_CLIENT_NAME_LEN) == 0) found = true;
|
||||
}
|
||||
if (!found) {
|
||||
@@ -206,24 +234,82 @@ void Radio::handleRequestPairing(struct requestPairing_s *request) {
|
||||
}
|
||||
}
|
||||
|
||||
void Radio::avoidChannelSwitchesFor_ms(unsigned int duration_ms) {
|
||||
long current_ts = millis();
|
||||
|
||||
if (nextClockAdvertisement_ts <= current_ts + duration_ms) {
|
||||
nextClockAdvertisement_ts = current_ts + duration_ms + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void Radio::listenOnlyFor_ms(unsigned int duration_ms) {
|
||||
unsigned long current_ts = millis();
|
||||
|
||||
if (nextSendMessage_ts <= current_ts + duration_ms) {
|
||||
nextSendMessage_ts = current_ts + duration_ms + 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool Radio::allowedToSendNow() {
|
||||
if (millis() >= nextSendMessage_ts) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Radio::checkClockAdvertisement() {
|
||||
unsigned long current_ts = millis();
|
||||
|
||||
if (current_ts >= nextClockAdvertisement_ts) {
|
||||
broadcastClockAdvertisement(clockName, clockChannel);
|
||||
nextClockAdvertisement_ts = current_ts + timeBetweenClockAdvertisements_ms;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Radio::checkPairingOffering() {
|
||||
unsigned long current_ts = millis();
|
||||
|
||||
if (current_ts >= nextPairingOfferingAnnouncement_ts) {
|
||||
broadcastOfferPairing(clockName, clockChannel);
|
||||
nextPairingOfferingAnnouncement_ts = current_ts + timeBetweenPairingOfferingAnnouncements_ms;
|
||||
avoidChannelSwitchesFor_ms(timeForClientsToRespond_ms);
|
||||
listenOnlyFor_ms(timeForClientsToRespond_ms);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Radio::loop(void) {
|
||||
// put your main code here, to run repeatedly:
|
||||
/****************** Ping Out Role ***************************/
|
||||
if (isMaster) {
|
||||
switchToReceiverRole(rf24);
|
||||
if (rf24.available()) {
|
||||
char buffer[32];
|
||||
rf24.read(buffer, 32);
|
||||
|
||||
// Spew it
|
||||
Serial.print(F("Received new message, type="));
|
||||
Serial.print(buffer[0]);
|
||||
Serial.print(F(", bytes 1="));
|
||||
Serial.print(buffer[1]);
|
||||
Serial.print(", 2=");
|
||||
Serial.print(buffer[2]);
|
||||
Serial.print(", 3=");
|
||||
Serial.println(buffer[3]);
|
||||
if (buffer[0] > 0) {
|
||||
Serial.print(F("Rx, t="));
|
||||
Serial.print(buffer[0], HEX);
|
||||
Serial.print(F(", msg="));
|
||||
Serial.print(buffer[1], HEX);
|
||||
Serial.print(", ");
|
||||
Serial.print(buffer[2], HEX);
|
||||
Serial.print(", ");
|
||||
Serial.print(buffer[3], HEX);
|
||||
Serial.print(", ");
|
||||
Serial.println(buffer[4], HEX);
|
||||
}
|
||||
}
|
||||
|
||||
// Tx handling
|
||||
if (allowedToSendNow()) {
|
||||
if (!checkPairingOffering()) {
|
||||
if (!checkClockAdvertisement()) {
|
||||
// nothing sent :-)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,8 +323,7 @@ void Radio::loop(void) {
|
||||
{
|
||||
unsigned long got_time;
|
||||
|
||||
if( radio.available()){
|
||||
// Variable for the received timestamp
|
||||
if (radio.available()) { // Variable for the received timestamp
|
||||
while (radio.available()) { // While there is data ready
|
||||
radio.read( &got_time, sizeof(unsigned long) ); // Get the payload
|
||||
}
|
||||
|
43
src/radio.h
43
src/radio.h
@@ -61,7 +61,29 @@ struct textMessage_s {
|
||||
|
||||
class Radio {
|
||||
public:
|
||||
Radio(Display *d, bool _isMaster):display(d), isMaster(_isMaster) { };
|
||||
Radio(Display *d, bool _isMaster):display(d), isMaster(_isMaster) {
|
||||
inTX = true;
|
||||
inRX = false;
|
||||
role = inRX;
|
||||
nextRequestToRegisterAnnouncement_ts = 0;
|
||||
nextClockAdvertisement_ts = 0;
|
||||
nextPairingOfferingAnnouncement_ts = 0;
|
||||
timeBetweenClockAdvertisements_ms = DEFAULT_TIME_BETWEEN_CLOCK_ADVERTISEMENTS_ms;
|
||||
timeForClientsToRespond_ms = DEFAULT_TIME_FOR_CLIENTS_TO_RESPOND_ms;
|
||||
timeBetweenPairingOfferingAnnouncements_ms = DEFAULT_TIME_BETWEEN_PAIRING_OFFERINGS_ms;
|
||||
nextSendMessage_ts = 0;
|
||||
clockChannel = DEFAULT_CLOCK_CHANNEL;
|
||||
strncpy(clockName, "defclk", MAX_CLOCK_NAME_LEN);
|
||||
};
|
||||
|
||||
void setClockName(const char *_clockName) {
|
||||
strncpy(clockName, _clockName, MAX_CLOCK_NAME_LEN);
|
||||
};
|
||||
|
||||
void setClockChannel(uint8_t _channel) {
|
||||
clockChannel = _channel;
|
||||
};
|
||||
|
||||
void begin(void);
|
||||
void loop(void);
|
||||
void broadcastClock(int day, int hour, int minute, int second, int msPerModelSecond);
|
||||
@@ -69,9 +91,28 @@ public:
|
||||
void broadcastTextMessage(const char *text);
|
||||
void handleRequestPairing(struct requestPairing_s *request);
|
||||
void ackPairingRequest(char *clientName, uint8_t clientNetworkAddress);
|
||||
void avoidChannelSwitchesFor_ms(unsigned int duration_ms);
|
||||
void listenOnlyFor_ms(unsigned int duration_ms);
|
||||
bool allowedToSendNow(void);
|
||||
private:
|
||||
Display *display;
|
||||
bool isMaster;
|
||||
void switchToSenderRole(void);
|
||||
void switchToReceiverRole(void);
|
||||
bool inTX, inRX, role;
|
||||
char clockName[MAX_CLOCK_NAME_LEN];
|
||||
void broadcastMessage(void *msg, int len);
|
||||
void broadcastMessageOnChannel(void *msg, int len, uint8_t channel);
|
||||
void broadcastClockAdvertisement(const char *clockName, uint8_t channel);
|
||||
bool checkPairingOffering(void); // returns true, if a message has been sent
|
||||
bool checkClockAdvertisement(void); // returns true, if a message has been sent
|
||||
unsigned long nextClockAdvertisement_ts;
|
||||
unsigned long timeBetweenClockAdvertisements_ms;
|
||||
unsigned long nextPairingOfferingAnnouncement_ts;
|
||||
unsigned long timeBetweenPairingOfferingAnnouncements_ms;
|
||||
unsigned long nextRequestToRegisterAnnouncement_ts;
|
||||
unsigned long timeForClientsToRespond_ms;
|
||||
unsigned long nextSendMessage_ts;
|
||||
uint8_t clockChannel;
|
||||
};
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user