switch to setup for Arduino Boards Manager

This commit is contained in:
Erik Tylek Kettenburg
2015-06-23 12:42:35 -07:00
parent bc55c9bb45
commit 6ca6b114d5
3581 changed files with 93 additions and 51 deletions

View File

@@ -0,0 +1,6 @@
SubDir TOP libraries RF24Network examples sensornet ;
LOCATE_SOURCE = $(SUBDIR)/$(PINS) ;
LOCATE_TARGET = $(SUBDIR)/$(PINS) ;
ArduinoWithLibs Main : RF24Network RF24 Tictocs SPI ;

View File

@@ -0,0 +1,4 @@
version.h
output/
ojam/
.*.swp

View File

@@ -0,0 +1,6 @@
SubDir TOP libraries RF24Network examples helloworld_rx ;
LOCATE_SOURCE = $(SUBDIR)/$(PINS) ;
LOCATE_TARGET = $(SUBDIR)/$(PINS) ;
ArduinoWithLibs Main : RF24Network RF24 Tictocs SPI ;

View File

@@ -0,0 +1,67 @@
/*
Copyright (C) 2012 James Coliz, Jr. <maniacbug@ymail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
/**
* Simplest possible example of using RF24Network,
*
* RECEIVER NODE
* Listens for messages from the transmitter and prints them out.
*/
#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>
// nRF24L01(+) radio attached using Getting Started board
RF24 radio(9,10);
// Network uses that radio
RF24Network network(radio);
// Address of our node
const uint16_t this_node = 0;
// Address of the other node
const uint16_t other_node = 1;
// Structure of our payload
struct payload_t
{
unsigned long ms;
unsigned long counter;
};
void setup(void)
{
Serial.begin(57600);
Serial.println("RF24Network/examples/helloworld_rx/");
SPI.begin();
radio.begin();
network.begin(/*channel*/ 90, /*node address*/ this_node);
}
void loop(void)
{
// Pump the network regularly
network.update();
// Is there anything ready for us?
while ( network.available() )
{
// If so, grab it and print it out
RF24NetworkHeader header;
payload_t payload;
network.read(header,&payload,sizeof(payload));
Serial.print("Received packet #");
Serial.print(payload.counter);
Serial.print(" at ");
Serial.println(payload.ms);
}
}
// vim:ai:cin:sts=2 sw=2 ft=cpp

View File

@@ -0,0 +1,4 @@
version.h
output/
ojam/
.*.swp

View File

@@ -0,0 +1,6 @@
SubDir TOP libraries RF24Network examples helloworld_tx ;
LOCATE_SOURCE = $(SUBDIR)/$(PINS) ;
LOCATE_TARGET = $(SUBDIR)/$(PINS) ;
ArduinoWithLibs Main : RF24Network RF24 Tictocs SPI ;

View File

@@ -0,0 +1,79 @@
/*
Copyright (C) 2012 James Coliz, Jr. <maniacbug@ymail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
/**
* Simplest possible example of using RF24Network
*
* TRANSMITTER NODE
* Every 2 seconds, send a payload to the receiver node.
*/
#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>
// nRF24L01(+) radio attached using Getting Started board
RF24 radio(9,10);
// Network uses that radio
RF24Network network(radio);
// Address of our node
const uint16_t this_node = 1;
// Address of the other node
const uint16_t other_node = 0;
// How often to send 'hello world to the other unit
const unsigned long interval = 2000; //ms
// When did we last send?
unsigned long last_sent;
// How many have we sent already
unsigned long packets_sent;
// Structure of our payload
struct payload_t
{
unsigned long ms;
unsigned long counter;
};
void setup(void)
{
Serial.begin(57600);
Serial.println("RF24Network/examples/helloworld_tx/");
SPI.begin();
radio.begin();
network.begin(/*channel*/ 90, /*node address*/ this_node);
}
void loop(void)
{
// Pump the network regularly
network.update();
// If it's time to send a message, send it!
unsigned long now = millis();
if ( now - last_sent >= interval )
{
last_sent = now;
Serial.print("Sending...");
payload_t payload = { millis(), packets_sent++ };
RF24NetworkHeader header(/*to node*/ other_node);
bool ok = network.write(header,&payload,sizeof(payload));
if (ok)
Serial.println("ok.");
else
Serial.println("failed.");
}
}
// vim:ai:cin:sts=2 sw=2 ft=cpp

View File

@@ -0,0 +1,12 @@
SubDir TOP ;
# Set up output directories
LOCATE_TARGET = $(SEARCH_SOURCE)/out/$(TOOLSET) ;
LOCATE_SOURCE = $(LOCATE_TARGET) ;
# Pull in local libraries
SKETCH_LIBS += RF24Network RF24 ;
HDRS += $(HOME)/Source/Arduino/libraries/$(SKETCH_LIBS) ;
# Main output executable
Maple $(SEARCH_SOURCE:B).elf : [ GLOB $(SEARCH_SOURCE) $(HOME)/Source/Arduino/libraries/$(SKETCH_LIBS) : $(MODULE_EXT) ] ;

View File

@@ -0,0 +1,237 @@
MCU = cortex-m3 ;
CHIP = STM32F103ZE ;
BOARD = maple_native ;
#CHIP = at91sam3u4 ;
#BOARD = sam3u-ek ;
if ! $(TOOLSET)
{
TOOLSET = mix ;
Echo "Assuming TOOLSET=mix" ;
}
else if $(TOOLSET) = cs
{
TOOLS_PATH = /opt/cs/arm/bin ;
TOOLS_ARCH = arm-none-eabi- ;
}
else if $(TOOLSET) = yagarto
{
TOOLS_PATH = ~/Source/yagarto-4.6.2/bin ;
TOOLS_ARCH = arm-none-eabi- ;
}
if $(TOOLSET) = yagarto-install
{
TOOLS_PATH = ~/Source/yagarto/install/bin ;
TOOLS_ARCH = arm-none-eabi- ;
}
else if $(TOOLSET) = devkit
{
TOOLS_PATH = /opt/devkitARM/bin ;
TOOLS_ARCH = arm-eabi- ;
}
else if $(TOOLSET) = maple
{
TOOLS_PATH = /opt/Maple/Resources/Java/hardware/tools/arm/bin ;
TOOLS_ARCH = arm-none-eabi- ;
LINK_DIR = /opt/Maple/Resources/Java/hardware/leaflabs/cores/maple ;
MAPLE_DIR = /opt/Maple/Resources/Java/hardware/leaflabs/cores/maple ;
MAPLE_SUBDIRS = . ;
}
else if $(TOOLSET) = mix
{
TOOLS_PATH = /opt/Maple/Resources/Java/hardware/tools/arm/bin ;
TOOLS_ARCH = arm-none-eabi- ;
LINKFLAGS += --print-gc-sections ;
}
else if $(TOOLSET) = ports
{
TOOLS_PATH = /opt/local/bin ;
TOOLS_ARCH = arm-none-eabi- ;
}
# Tool locations
CC = $(TOOLS_PATH)/$(TOOLS_ARCH)gcc ;
C++ = $(TOOLS_PATH)/$(TOOLS_ARCH)g++ ;
AS = $(TOOLS_PATH)/$(TOOLS_ARCH)gcc -c ;
LINK = $(TOOLS_PATH)/$(TOOLS_ARCH)g++ ;
OBJCOPY = $(TOOLS_PATH)/$(TOOLS_ARCH)objcopy ;
DFU = dfu-util ;
# Flags
DEFINES += VECT_TAB_FLASH BOARD_$(BOARD) MCU_$(CHIP) ERROR_LED_PORT=GPIOC ERROR_LED_PIN=15 STM32_HIGH_DENSITY MAPLE_IDE ;
OPTIM = -Os ;
MFLAGS = cpu=$(MCU) thumb arch=armv7-m ;
CCFLAGS = -Wall -m$(MFLAGS) -g -nostdlib -ffunction-sections -fdata-sections -Wl,--gc-sections ;
C++FLAGS = $(CCFLAGS) -fno-rtti -fno-exceptions ;
LINKFLAGS += -m$(MFLAGS) -Xlinker --gc-sections ;
DFUFLAGS = -a1 -d 0x1eaf:0x0003 -R ;
# Directories
MAPLE_DIR ?= /opt/libmaple ;
MAPLE_LIBS = Servo LiquidCrystal Wire FreeRTOS ;
MAPLE_SUBDIRS ?= libmaple libmaple/usb libmaple/usb/usb_lib wirish wirish/comm wirish/boards ;
SKETCH_DIR = $(HOME)/Source/Maple ;
CORE_DIRS = $(MAPLE_DIR)/$(MAPLE_SUBDIRS) $(MAPLE_DIR)/libraries/$(MAPLE_LIBS) ;
HDRS = $(CORE_DIRS) ;
# Modules
MODULE_EXT = *.c *.cpp *.S *.pde *.ino *.test ;
CORE_MODULES = [ GLOB $(CORE_DIRS) : $(MODULE_EXT) ] ;
# Unit test framework
CXXTEST_DIR = $(HOME)/Source/cxxtest ;
#CXXTEST_GEN = $(CXXTEST_DIR)/cxxtestgen.py ;
CXXTEST_GEN = $(CXXTEST_DIR)/python/scripts/cxxtestgen ;
HDRS += $(CXXTEST_DIR) ;
# Linker script
LINK_DIR ?= $(MAPLE_DIR)/support/ld ;
LINKSCRIPT = $(LINK_DIR)/$(BOARD)/flash.ld ;
LINKFLAGS += -T$(LINKSCRIPT) -L$(LINK_DIR) ;
rule Pde
{
Depends $(<) : $(>) ;
MakeLocate $(<) : $(LOCATE_SOURCE) ;
Clean clean : $(<) ;
}
if ( $(ARDUINO_VERSION) < 100 )
{
ARDUINO_H = WProgram.h ;
}
else
{
ARDUINO_H = Arduino.h ;
}
actions Pde
{
echo "#include <$(ARDUINO_H)>" > $(<)
echo "#line 1 \"$(>)\"" >> $(<)
cat $(>) >> $(<)
}
rule C++Pde
{
local _CPP = $(>:B).cpp ;
Pde $(_CPP) : $(>) ;
C++ $(<) : $(_CPP) ;
}
rule TestSuite
{
Depends $(<) : $(>) ;
MakeLocate $(<) : $(LOCATE_SOURCE) ;
Clean clean : $(<) ;
}
actions TestSuite
{
$(CXXTEST_GEN) --part $(>) > $(<)
}
rule TestRoot
{
MakeLocate $(<) : $(LOCATE_SOURCE) ;
}
actions TestRoot
{
$(CXXTEST_GEN) --root --error-printer > $(<)
}
rule C++TestSuite
{
local _CPP = $(>:B).cpp ;
TestSuite $(_CPP) : $(>) ;
C++ $(<) : $(_CPP) ;
}
rule Hex
{
Depends $(<) : $(>) ;
MakeLocate $(<) : $(LOCATE_TARGET) ;
Depends hex : $(<) ;
Clean clean : $(<) ;
}
actions Hex
{
$(OBJCOPY) -O ihex $(>) $(<)
}
rule Binary
{
Depends $(<) : $(>) ;
MakeLocate $(<) : $(LOCATE_TARGET) ;
Depends binary : $(<) ;
Clean clean : $(<) ;
}
actions Binary
{
$(OBJCOPY) -O binary $(>) $(<)
}
rule UserObject
{
switch $(>:S)
{
case .S : As $(<) : $(>) ;
case .ino : C++Pde $(<) : $(>) ;
case .pde : C++Pde $(<) : $(>) ;
case .test : C++TestSuite $(<) : $(>) ;
}
}
rule Upload
{
Depends up : $(<) ;
NotFile up ;
Always $(<) ;
Always up ;
}
actions Upload
{
$(DFU) $(DFUFLAGS) -D $(<)
}
# Override base objects rule, so all output can go in the output dir
rule Objects
{
local _i ;
for _i in [ FGristFiles $(<) ]
{
local _b = $(_i:B)$(SUFOBJ) ;
local _o = $(_b:G=$(SOURCE_GRIST:E)) ;
Object $(_o) : $(_i) ;
Depends obj : $(_o) ;
}
}
# Override base main rule, so all output can go in the output dir
rule Main
{
# Bring in the map
LINKFLAGS on $(<) = $(LINKFLAGS) -Wl,-Map=$(LOCATE_TARGET)/$(<:B).map ;
MakeLocate $(<) ;
MainFromObjects $(<) : $(>:B)$(SUFOBJ) ;
Objects $(>) ;
}
rule Maple
{
Main $(<) : $(>) $(CORE_MODULES) ;
Binary $(<:B).bin : $(<) ;
Upload $(<:B).bin ;
}

View File

@@ -0,0 +1,106 @@
/*
Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
/**
* Simplest possible example of using RF24Network
*
* TRANSMITTER NODE
* Every 2 seconds, says hello to the receiver node.
*/
#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>
//
// Maple specific setup. Other than this section, the sketch is the same on Maple as on
// Arduino
//
#ifdef MAPLE_IDE
// External startup function
extern void board_start(const char* program_name);
// Use SPI #2.
HardwareSPI SPI(2);
inline void serial_begin(int _baud)
{
}
#else
inline void serial_begin(int _baud)
{
Serial.begin(_baud);
}
#define board_startup printf
#define toggleLED(x) (x)
#endif
//
// Hardware configuration
//
// Set up nRF24L01 radio on SPI bus plus pins 7 & 6
// (This works for the Getting Started board plugged into the
// Maple Native backwards.)
RF24 radio(7,6);
// Network uses that radio
RF24Network network(radio);
// Address of our node
const uint16_t this_node = 1;
// Address of the other node
const uint16_t other_node = 0;
// How often to send 'hello world to the other unit
const unsigned long interval = 2000; //ms
// When did we last send?
unsigned long last_sent;
void setup(void)
{
serial_begin(57600);
board_start("RF24Network/examples/helloworld_tx/");
SPI.begin();
radio.begin();
network.begin(/*channel*/ 90, /*node address*/ this_node);
}
void loop(void)
{
// Pump the network regularly
network.update();
// If it's time to send a message, send it!
unsigned long now = millis();
if ( now - last_sent > interval )
{
last_sent = now;
toggleLED();
printf("Sending...\r\n");
const char* hello = "Hello, world!";
RF24NetworkHeader header(/*to node*/ other_node);
bool ok = network.write(header,hello,strlen(hello));
if (ok)
printf("\tok.\r\n");
else
{
printf("\tfailed.\r\n");
delay(250); // extra delay on fail to keep light on longer
}
toggleLED();
}
}
// vim:ai:cin:sts=2 sw=2 ft=cpp

View File

@@ -0,0 +1,77 @@
#ifdef MAPLE_IDE
#include <stdio.h>
#include "wirish.h"
extern void setup(void);
extern void loop(void);
void board_start(const char* program_name)
{
// Set up the LED to steady on
pinMode(BOARD_LED_PIN, OUTPUT);
digitalWrite(BOARD_LED_PIN, HIGH);
// Setup the button as input
pinMode(BOARD_BUTTON_PIN, INPUT);
digitalWrite(BOARD_BUTTON_PIN, HIGH);
SerialUSB.begin();
SerialUSB.println("Press BUT");
// Wait for button press
while ( !isButtonPressed() )
{
}
SerialUSB.println("Welcome!");
SerialUSB.println(program_name);
int i = 11;
while (i--)
{
toggleLED();
delay(50);
}
}
/**
* Custom version of _write, which will print to the USB.
* In order to use it you MUST ADD __attribute__((weak))
* to _write in libmaple/syscalls.c
*/
extern "C" int _write(int file, char * ptr, int len)
{
if ( (file != 1) && (file != 2) )
return 0;
else
SerialUSB.write(ptr,len);
return len;
}
__attribute__((constructor)) __attribute__ ((weak)) void premain()
{
init();
}
__attribute__((weak)) void setup(void)
{
board_start("No program defined");
}
__attribute__((weak)) void loop(void)
{
}
__attribute__((weak)) int main(void)
{
setup();
while (true)
{
loop();
}
return 0;
}
#endif // ifdef MAPLE_IDE
// vim:cin:ai:sts=2 sw=2 ft=cpp

View File

@@ -0,0 +1,4 @@
version.h
output/
ojam/
.*.swp

View File

@@ -0,0 +1,6 @@
SubDir TOP libraries RF24Network examples meshping ;
LOCATE_SOURCE = $(SUBDIR)/$(PINS) ;
LOCATE_TARGET = $(SUBDIR)/$(PINS) ;
ArduinoWithLibs Main : RF24Network RF24 Tictocs SPI ;

View File

@@ -0,0 +1,260 @@
/*
Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
/**
* Example of pinging across a mesh network
*
* Using this sketch, each node will send a ping to every other node
* in the network every few seconds.
* The RF24Network library will route the message across
* the mesh to the correct node.
*
* This sketch is greatly complicated by the fact that at startup time, each
* node (including the base) has no clue what nodes are alive. So,
* each node builds an array of nodes it has heard about. The base
* periodically sends out its whole known list of nodes to everyone.
*
* To see the underlying frames being relayed, compile RF24Network with
* #define SERIAL_DEBUG.
*
* The logical node address of each node is set in EEPROM. The nodeconfig
* module handles this by listening for a digit (0-9) on the serial port,
* and writing that number to EEPROM.
*
* To use the sketch, upload it to two or more units. Run each one in
* turn. Attach a serial monitor, and send a single-digit address to
* each. Make the first one '0', and the following units '1', '2', etc.
*/
#include <avr/pgmspace.h>
#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>
#include "nodeconfig.h"
#include "printf.h"
// This is for git version tracking. Safe to ignore
#ifdef VERSION_H
#include "version.h"
#else
#define __TAG__ "Unknown"
#endif
// nRF24L01(+) radio using the Getting Started board
RF24 radio(9,10);
RF24Network network(radio);
// Our node address
uint16_t this_node;
// Delay manager to send pings regularly
const unsigned long interval = 2000; // ms
unsigned long last_time_sent;
// Array of nodes we are aware of
const short max_active_nodes = 10;
uint16_t active_nodes[max_active_nodes];
short num_active_nodes = 0;
short next_ping_node_index = 0;
// Prototypes for functions to send & handle messages
bool send_T(uint16_t to);
bool send_N(uint16_t to);
void handle_T(RF24NetworkHeader& header);
void handle_N(RF24NetworkHeader& header);
void add_node(uint16_t node);
void setup(void)
{
//
// Print preamble
//
Serial.begin(57600);
printf_begin();
printf_P(PSTR("\n\rRF24Network/examples/meshping/\n\r"));
printf_P(PSTR("VERSION: " __TAG__ "\n\r"));
//
// Pull node address out of eeprom
//
// Which node are we?
this_node = nodeconfig_read();
//
// Bring up the RF network
//
SPI.begin();
radio.begin();
network.begin(/*channel*/ 100, /*node address*/ this_node );
}
void loop(void)
{
// Pump the network regularly
network.update();
// Is there anything ready for us?
while ( network.available() )
{
// If so, take a look at it
RF24NetworkHeader header;
network.peek(header);
// Dispatch the message to the correct handler.
switch (header.type)
{
case 'T':
handle_T(header);
break;
case 'N':
handle_N(header);
break;
default:
printf_P(PSTR("*** WARNING *** Unknown message type %c\n\r"),header.type);
network.read(header,0,0);
break;
};
}
// Send a ping to the next node every 'interval' ms
unsigned long now = millis();
if ( now - last_time_sent >= interval )
{
last_time_sent = now;
// Who should we send to?
// By default, send to base
uint16_t to = 00;
// Or if we have active nodes,
if ( num_active_nodes )
{
// Send to the next active node
to = active_nodes[next_ping_node_index++];
// Have we rolled over?
if ( next_ping_node_index > num_active_nodes )
{
// Next time start at the beginning
next_ping_node_index = 0;
// This time, send to node 00.
to = 00;
}
}
bool ok;
// Normal nodes send a 'T' ping
if ( this_node > 00 || to == 00 )
ok = send_T(to);
// Base node sends the current active nodes out
else
ok = send_N(to);
// Notify us of the result
if (ok)
{
printf_P(PSTR("%lu: APP Send ok\n\r"),millis());
}
else
{
printf_P(PSTR("%lu: APP Send failed\n\r"),millis());
// Try sending at a different time next time
last_time_sent -= 100;
}
}
// Listen for a new node address
nodeconfig_listen();
}
/**
* Send a 'T' message, the current time
*/
bool send_T(uint16_t to)
{
RF24NetworkHeader header(/*to node*/ to, /*type*/ 'T' /*Time*/);
// The 'T' message that we send is just a ulong, containing the time
unsigned long message = millis();
printf_P(PSTR("---------------------------------\n\r"));
printf_P(PSTR("%lu: APP Sending %lu to 0%o...\n\r"),millis(),message,to);
return network.write(header,&message,sizeof(unsigned long));
}
/**
* Send an 'N' message, the active node list
*/
bool send_N(uint16_t to)
{
RF24NetworkHeader header(/*to node*/ to, /*type*/ 'N' /*Time*/);
printf_P(PSTR("---------------------------------\n\r"));
printf_P(PSTR("%lu: APP Sending active nodes to 0%o...\n\r"),millis(),to);
return network.write(header,active_nodes,sizeof(active_nodes));
}
/**
* Handle a 'T' message
*
* Add the node to the list of active nodes
*/
void handle_T(RF24NetworkHeader& header)
{
// The 'T' message is just a ulong, containing the time
unsigned long message;
network.read(header,&message,sizeof(unsigned long));
printf_P(PSTR("%lu: APP Received %lu from 0%o\n\r"),millis(),message,header.from_node);
// If this message is from ourselves or the base, don't bother adding it to the active nodes.
if ( header.from_node != this_node || header.from_node > 00 )
add_node(header.from_node);
}
/**
* Handle an 'N' message, the active node list
*/
void handle_N(RF24NetworkHeader& header)
{
static uint16_t incoming_nodes[max_active_nodes];
network.read(header,&incoming_nodes,sizeof(incoming_nodes));
printf_P(PSTR("%lu: APP Received nodes from 0%o\n\r"),millis(),header.from_node);
int i = 0;
while ( i < max_active_nodes && incoming_nodes[i] > 00 )
add_node(incoming_nodes[i++]);
}
/**
* Add a particular node to the current list of active nodes
*/
void add_node(uint16_t node)
{
// Do we already know about this node?
short i = num_active_nodes;
while (i--)
{
if ( active_nodes[i] == node )
break;
}
// If not, add it to the table
if ( i == -1 && num_active_nodes < max_active_nodes )
{
active_nodes[num_active_nodes++] = node;
printf_P(PSTR("%lu: APP Added 0%o to list of active nodes.\n\r"),millis(),node);
}
}
// vim:ai:cin:sts=2 sw=2 ft=cpp

View File

@@ -0,0 +1,69 @@
/*
Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
#include "RF24Network_config.h"
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
#include "nodeconfig.h"
// Where in EEPROM is the address stored?
uint8_t* address_at_eeprom_location = (uint8_t*)10;
// What flag value is stored there so we know the value is valid?
const uint8_t valid_eeprom_flag = 0xdf;
// What are the actual node values that we want to use?
// EEPROM locations are actually just indices into this array
const uint16_t node_address_set[10] = { 00, 02, 05, 012, 015, 022, 025, 032, 035, 045 };
uint8_t nodeconfig_read(void)
{
uint8_t result = 0;
// Look for the token in EEPROM to indicate the following value is
// a validly set node address
if ( eeprom_read_byte(address_at_eeprom_location) == valid_eeprom_flag )
{
// Read the address from EEPROM
result = node_address_set[ eeprom_read_byte(address_at_eeprom_location+1) ];
printf_P(PSTR("ADDRESS: %u\n\r"),result);
}
else
{
printf_P(PSTR("*** No valid address found. Send 0-9 via serial to set node address\n\r"));
while(1)
{
nodeconfig_listen();
}
}
return result;
}
void nodeconfig_listen(void)
{
//
// Listen for serial input, which is how we set the address
//
if (Serial.available())
{
// If the character on serial input is in a valid range...
char c = Serial.read();
if ( c >= '0' && c <= '9' )
{
// It is our address
eeprom_write_byte(address_at_eeprom_location,valid_eeprom_flag);
eeprom_write_byte(address_at_eeprom_location+1,c-'0');
// And we are done right now (no easy way to soft reset)
printf_P(PSTR("\n\rManually reset index to: %c, address 0%o\n\rPress RESET to continue!"),c,node_address_set[c-'0']);
while(1);
}
}
}
// vim:ai:cin:sts=2 sw=2 ft=cpp

View File

@@ -0,0 +1,15 @@
/*
Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
#ifndef __NODECONFIG_H__
#define __NODECONFIG_H__
uint8_t nodeconfig_read(void);
void nodeconfig_listen(void);
#endif // __NODECONFIG_H__

View File

@@ -0,0 +1,37 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
/**
* @file printf.h
*
* Setup necessary to direct stdout to the Arduino Serial library, which
* enables 'printf'
*/
#ifndef __PRINTF_H__
#define __PRINTF_H__
#ifdef ARDUINO
int serial_putc( char c, FILE * )
{
Serial.write( c );
return c;
}
void printf_begin(void)
{
fdevopen( &serial_putc, 0 );
}
#else
#error This example is only for use on Arduino.
#endif // ARDUINO
#endif // __PRINTF_H__

View File

@@ -0,0 +1,4 @@
version.h
output/
ojam/
.*.swp

View File

@@ -0,0 +1,30 @@
#ifndef __DUINODE_V3_H__
#define __DUINODE_V3_H__
/**
* @file DuinodeV1.h
*
* Contains hardware definitions for RF Duinode V1 (3V3)
*/
#define PINS_DEFINED 1
#define __PLATFORM__ "RF Duinode V1 (3V3)"
const int rf_irq = 0;
const int led_red = 0;
const int led_yellow = 0;
const int led_green = 0;
const int button_a = 0;
const int rf_ce = 8;
const int rf_csn = 9;
const int temp_pin = 2; // analog
const int voltage_pin = 3; // analog
// 1.1V internal reference after 1M/470k divider, in 8-bit fixed point
const unsigned voltage_reference = 0x371;
#endif // __DUINODE_V3_H__
// vim:cin:ai:sts=2 sw=2 ft=cpp

View File

@@ -0,0 +1,30 @@
#ifndef __DUINODE_V3_H__
#define __DUINODE_V3_H__
/**
* @file DuinodeV3.h
*
* Contains hardware definitions for RF Duinode V3 (2V4)
*/
#define PINS_DEFINED 1
#define __PLATFORM__ "RF Duinode V3/V4 (2V4)"
const int rf_irq = 0;
const int led_red = 3;
const int led_yellow = 4;
const int led_green = 5;
const int button_a = 6;
const int rf_ce = 8;
const int rf_csn = 7;
const int temp_pin = 2; // analog
const int voltage_pin = 3; // analog
// 1.1V internal reference after 1M/470k divider, in 8-bit fixed point
const unsigned voltage_reference = 0x371;
#endif // __DUINODE_V3_H__
// vim:cin:ai:sts=2 sw=2 ft=cpp

View File

@@ -0,0 +1,30 @@
#ifndef __DUINODE_V5_H__
#define __DUINODE_V5_H__
/**
* @file DuinodeV3.h
*
* Contains hardware definitions for RF Duinode V5 (2V4)
*/
#define PINS_DEFINED 1
#define __PLATFORM__ "RF Duinode V5 (2V4)"
const int rf_irq = 0;
const int led_red = 3;
const int led_yellow = 4;
const int led_green = 5;
const int button_a = 6;
const int rf_ce = 14;
const int rf_csn = 15;
const int temp_pin = 2; // analog
const int voltage_pin = 3; // analog
// 1.1V internal reference after 1M/470k divider, in 8-bit fixed point
const unsigned voltage_reference = 0x371;
#endif // __DUINODE_V5_H__
// vim:cin:ai:sts=2 sw=2 ft=cpp

View File

@@ -0,0 +1,6 @@
SubDir TOP libraries RF24Network examples sensornet ;
LOCATE_SOURCE = $(SUBDIR)/$(PINS) ;
LOCATE_TARGET = $(SUBDIR)/$(PINS) ;
ArduinoWithLibs Main : RF24Network RF24 Tictocs SPI ;

View File

@@ -0,0 +1,34 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
// STL headers
// C headers
// Framework headers
// Library headers
#include "RF24Network_config.h"
// Project headers
// This component's header
#include "S_message.h"
char S_message::buffer[32];
/****************************************************************************/
char* S_message::toString(void)
{
snprintf(buffer,sizeof(buffer),"%2u.%02uC /%2u.%02uV",
temp_reading >> 8,
( temp_reading & 0xFF ) * 100 / 256,
voltage_reading >> 8,
( voltage_reading & 0xFF ) * 100 / 256
);
return buffer;
}
/****************************************************************************/
// vim:cin:ai:sts=2 sw=2 ft=cpp

View File

@@ -0,0 +1,32 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
#ifndef __S_MESSAGE_H__
#define __S_MESSAGE_H__
// STL headers
// C headers
// Framework headers
// Library headers
// Project headers
/**
* Sensor message (type 'S')
*/
struct S_message
{
uint16_t temp_reading;
uint16_t voltage_reading;
static char buffer[];
S_message(void): temp_reading(0), voltage_reading(0) {}
char* toString(void);
};
#endif // __S_MESSAGE_H__
// vim:cin:ai:sts=2 sw=2 ft=cpp

View File

@@ -0,0 +1 @@
jam F_CPU=16000000 "CCFLAGS=-include DuinodeV1.h" -dx UPLOAD_SPEED=115200 u1 && screen /dev/ttyUSB1 57600

View File

@@ -0,0 +1,3 @@
AVR_BIN=/usr/local/avr/bin AVR_ETC=/usr/local/avr/etc jam F_CPU=8000000 sensornet.elf
touch sensornet.pde
AVR_BIN=/usr/local/avr/bin AVR_ETC=/usr/local/avr/etc jam F_CPU=8000000 "CCFLAGS=-include DuinodeV3.h" -dx UPLOAD_SPEED=57600 u1 && screen /dev/ttyUSB1 57600

View File

@@ -0,0 +1 @@
jam F_CPU=8000000 "CCFLAGS=-include DuinodeV5.h" -dx UPLOAD_SPEED=57600 u0 && picocom -b 57600 /dev/ttyUSB0

View File

@@ -0,0 +1,131 @@
/*
Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
#include "RF24Network_config.h"
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
#include "nodeconfig.h"
// Where in EEPROM is the address stored?
uint8_t* address_at_eeprom_location = (uint8_t*)10;
eeprom_info_t eeprom_info;
const eeprom_info_t& nodeconfig_read(void)
{
eeprom_read_block(&eeprom_info,address_at_eeprom_location,sizeof(eeprom_info));
// Look for the token in EEPROM to indicate the following value is
// a validly set node address
if ( eeprom_info.isValid() )
{
printf_P(PSTR("ADDRESS: %o\n\r"),eeprom_info.address);
printf_P(PSTR("ROLE: %S\n\r"),eeprom_info.relay ? PSTR("Relay") : PSTR("Leaf") );
printf_P(PSTR("TEMP: %04x\n\r"),eeprom_info.temp_calibration);
}
else
{
eeprom_info.clear();
printf_P(PSTR("*** No valid address found. Send node address via serial of the form 011<cr>\n\r"));
while(1)
{
nodeconfig_listen();
}
}
return eeprom_info;
}
char serialdata[10];
char* nextserialat = serialdata;
const char* maxserial = serialdata + sizeof(serialdata) - 1;
void nodeconfig_listen(void)
{
//
// Listen for serial input, which is how we set the address
//
if (Serial.available())
{
// If the character on serial input is in a valid range...
char c = tolower(Serial.read());
if ( (c >= '0' && c <= '9' ) || (c >= 'a' && c <= 'f' ) )
{
*nextserialat++ = c;
if ( nextserialat == maxserial )
{
*nextserialat = 0;
printf_P(PSTR("\r\n*** Unknown serial command: %s\r\n"),serialdata);
nextserialat = serialdata;
}
}
else if ( tolower(c) == 'r' )
{
eeprom_info.relay = true;
printf_P(PSTR("ROLE: %S\n\r"),eeprom_info.relay ? PSTR("Relay") : PSTR("Leaf") );
eeprom_update_block(&eeprom_info,address_at_eeprom_location,sizeof(eeprom_info));
printf_P(PSTR("RESET NODE before changes take effect\r\n"));
if ( ! eeprom_info.isValid() )
printf_P(PSTR("Please assign an address\r\n"));
}
else if ( tolower(c) == 'l' )
{
eeprom_info.relay = false;
printf_P(PSTR("ROLE: %S\n\r"),eeprom_info.relay ? PSTR("Relay") : PSTR("Leaf") );
eeprom_update_block(&eeprom_info,address_at_eeprom_location,sizeof(eeprom_info));
printf_P(PSTR("RESET NODE before changes take effect\r\n"));
if ( ! eeprom_info.isValid() )
printf_P(PSTR("Please assign an address\r\n"));
}
else if ( tolower(c) == 't' )
{
// Send temperature calibration as 2-digit 4.4-fixed decimal signed degrees
// celcius--followed by a 't'. So, for -1.5 degrees, send "e8t". Or for +2 degrees
// send "20t"
*nextserialat = 0;
int8_t val = strtol(serialdata,NULL,16);
nextserialat = serialdata;
set_temp_calibration( val * 0x10 );
printf_P(PSTR("RESET NODE before changes take effect\r\n"));
if ( ! eeprom_info.isValid() )
printf_P(PSTR("Please assign an address\r\n"));
}
else if ( c == 13 )
{
// Convert to octal
char *pc = serialdata;
uint16_t address = 0;
while ( pc < nextserialat )
{
address <<= 3;
address |= (*pc++ - '0');
}
// It is our address
eeprom_info.address = address;
eeprom_update_block(&eeprom_info,address_at_eeprom_location,sizeof(eeprom_info));
// And we are done right now (no easy way to soft reset)
printf_P(PSTR("\n\rManually set to address 0%o\n\rPress RESET to continue!"),address);
while(1);
}
}
}
void set_temp_calibration(int16_t val)
{
eeprom_info.temp_calibration = val;
printf_P(PSTR("TEMP: %02x\n\r"),eeprom_info.temp_calibration);
eeprom_update_block(&eeprom_info,address_at_eeprom_location,sizeof(eeprom_info));
}
// vim:ai:cin:sts=2 sw=2 ft=cpp

View File

@@ -0,0 +1,49 @@
/*
Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
#ifndef __NODECONFIG_H__
#define __NODECONFIG_H__
// Additional info
struct eeprom_info_t
{
uint8_t flag;
uint16_t address;
int16_t temp_calibration; // sensor adjustment in signed fixed-8.8 degrees, e.g. 0xFE80 is -1.5
bool relay:1;
static const uint8_t valid_flag = 0xdd;
eeprom_info_t()
{
clear();
}
bool isValid() const
{
return (flag == valid_flag) && (address != 0xffff);
}
void clear()
{
flag = valid_flag;
address = 0xffff;
relay = false;
temp_calibration = 0;
}
};
const eeprom_info_t& nodeconfig_read(void);
void nodeconfig_listen(void);
void set_temp_calibration(int16_t val);
#endif // __NODECONFIG_H__
// vim:ai:cin:sts=2 sw=2 ft=cpp

View File

@@ -0,0 +1,37 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
/**
* @file printf.h
*
* Setup necessary to direct stdout to the Arduino Serial library, which
* enables 'printf'
*/
#ifndef __PRINTF_H__
#define __PRINTF_H__
#ifdef ARDUINO
int serial_putc( char c, FILE * )
{
Serial.write( c );
return c;
}
void printf_begin(void)
{
fdevopen( &serial_putc, 0 );
}
#else
#error This example is only for use on Arduino.
#endif // ARDUINO
#endif // __PRINTF_H__

View File

@@ -0,0 +1,498 @@
/*
Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
/**
* Example of a sensor network
*
* This sketch demonstrates how to use the RF24Network library to
* manage a set of low-power sensor nodes which mostly sleep but
* awake regularly to send readings to the base.
*
* The example uses TWO sensors, a 'temperature' sensor and a 'voltage'
* sensor.
*
* To see the underlying frames being relayed, compile RF24Network with
* #define SERIAL_DEBUG.
*
* The logical node address of each node is set in EEPROM. The nodeconfig
* module handles this by listening for a digit (0-9) on the serial port,
* and writing that number to EEPROM.
*/
#include <avr/pgmspace.h>
#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>
#include <Tictocs.h>
#include <Button.h>
#include <TictocTimer.h>
#include "nodeconfig.h"
#include "sleep.h"
#include "S_message.h"
#include "printf.h"
// This is for git version tracking. Safe to ignore
#ifdef VERSION_H
#include "version.h"
#else
#define __TAG__ "Unknown"
#endif
// Pin definitions
#ifndef PINS_DEFINED
#define __PLATFORM__ "Getting Started board"
// Pins for radio
const int rf_ce = 9;
const int rf_csn = 10;
// Pins for sensors
const int temp_pin = A2;
const int voltage_pin = A3;
// Pins for status LED, or '0' for no LED connected
const int led_red = 0;
const int led_yellow = 0;
const int led_green = 0;
// Button to control modes
const int button_a = 4;
// What voltage is a reading of 1023?
const unsigned voltage_reference = 5 * 256; // 5.0V
#endif
RF24 radio(rf_ce,rf_csn);
RF24Network network(radio);
// Our node configuration
eeprom_info_t this_node;
// Sleep constants. In this example, the watchdog timer wakes up
// every 4s, and every single wakeup we power up the radio and send
// a reading. In real use, these numbers which be much higher.
// Try wdt_8s and 7 cycles for one reading per minute.> 1
const wdt_prescalar_e wdt_prescalar = wdt_8s;
const int sleep_cycles_per_transmission = 1;
// Non-sleeping nodes need a timer to regulate their sending interval
Timer send_timer(8000);
// Button controls functionality of the unit
Button ButtonA(button_a);
// Long-press button
Button ButtonLong(button_a,1000);
/**
* Convenience class for handling LEDs. Handles the case where the
* LED may not be populated on the board, so always checks whether
* the pin is valid before setting a value.
*/
class LED
{
private:
int pin;
public:
LED(int _pin): pin(_pin)
{
if (pin > 0)
{
pinMode(pin,OUTPUT);
digitalWrite(pin,LOW);
}
}
void write(bool state) const
{
if (pin > 0)
digitalWrite(pin,state?HIGH:LOW);
}
void operator=(bool state)
{
write(state);
}
};
/**
* Startup LED sequence. Lights up the LEDs in sequence first, then dims
* them in the same sequence.
*/
class StartupLEDs: public Timer
{
private:
const LED** leds;
const LED** current;
const LED** end;
bool state;
protected:
virtual void onFired(void)
{
(*current)->write(state);
++current;
if ( current >= end )
{
if ( state )
{
state = false;
current = leds;
}
else
disable();
}
}
public:
StartupLEDs(const LED** _leds, int _num): Timer(250), leds(_leds), current(_leds), end(_leds+_num), state(true)
{
}
};
/**
* Calibration LED sequence. Flashes all 3 in unison
*/
class CalibrationLEDs: public Timer
{
const LED** leds;
const LED** end;
bool state;
protected:
void write()
{
const LED** current = end;
while (current-- > leds)
(*current)->write(state);
}
virtual void onFired()
{
state = ! state;
write();
}
public:
CalibrationLEDs(const LED** _leds, int _num, unsigned long duration = 500): Timer(duration), leds(_leds), end(_leds+_num), state(false)
{
Timer::disable();
}
void begin()
{
Updatable::begin();
}
void reset()
{
state = true;
write();
Timer::reset();
}
void disable()
{
state = false;
write();
Timer::disable();
}
};
LED Red(led_red), Yellow(led_yellow), Green(led_green);
const LED* leds[] = { &Red, &Yellow, &Green };
const int num_leds = sizeof(leds)/sizeof(leds[0]);
StartupLEDs startup_leds(leds,num_leds);
CalibrationLEDs calibration_leds(leds,num_leds);
// Nodes in test mode do not sleep, but instead constantly try to send
bool test_mode = false;
// Nodes in calibration mode are looking for temperature calibration
bool calibration_mode = false;
// Helper functions to take readings
// How many measurements to take. 64*1024 = 65536, so 64 is the max we can fit in a uint16_t.
const int num_measurements = 64;
uint32_t measure_temp()
{
int i = num_measurements;
uint32_t reading = 0;
while(i--)
reading += analogRead(temp_pin);
// Convert the reading to celcius*256
// This is the formula for MCP9700.
// C = reading * 1.1
// C = ( V - 1/2 ) * 100
//
// Then adjust for the calibation value on this sensor
return ( ( ( ( reading * 0x120 ) - 0x800000 ) * 0x64 ) >> 16 ) + this_node.temp_calibration;
}
uint32_t measure_voltage()
{
// Take the voltage reading
int i = num_measurements;
uint32_t reading = 0;
while(i--)
reading += analogRead(voltage_pin);
// Convert the voltage reading to volts*256
return ( reading * voltage_reference ) >> 16;
}
struct CalibrationData
{
uint8_t measurements_remaining;
static const uint8_t measurements_needed = 16;
int16_t accumulator;
CalibrationData()
{
measurements_remaining = measurements_needed;
accumulator = 0;
}
void add(int16_t reading)
{
accumulator += reading / measurements_needed;
if ( measurements_remaining )
--measurements_remaining;
}
bool done() const
{
return measurements_remaining == 0;
}
int16_t result() const
{
return accumulator;
}
};
CalibrationData calibration_data;
void setup(void)
{
//
// Print preamble
//
Serial.begin(57600);
printf_begin();
printf_P(PSTR("\n\rRF24Network/examples/sensornet/\n\r"));
printf_P(PSTR("PLATFORM: " __PLATFORM__ "\n\r"));
printf_P(PSTR("VERSION: " __TAG__ "\n\r"));
//
// Pull node address out of eeprom
//
// Which node are we?
this_node = nodeconfig_read();
//
// Prepare sleep parameters
//
// Only the leaves sleep. Nodes 01-05 are presumed to be relay nodes.
if ( ! this_node.relay )
Sleep.begin(wdt_prescalar,sleep_cycles_per_transmission);
//
// Set up board hardware
//
ButtonA.begin();
ButtonLong.begin();
// Sensors use the stable internal 1.1V voltage
#ifdef INTERNAL1V1
analogReference(INTERNAL1V1);
#else
analogReference(INTERNAL);
#endif
// Prepare the startup sequence
send_timer.begin();
startup_leds.begin();
calibration_leds.begin();
//
// Bring up the RF network
//
SPI.begin();
radio.begin();
network.begin(/*channel*/ 92, /*node address*/ this_node.address);
}
void loop(void)
{
// Update objects
theUpdater.update();
// Pump the network regularly
network.update();
// Is there anything ready for us?
while ( network.available() )
{
// If so, grab it and print it out
RF24NetworkHeader header;
S_message message;
network.read(header,&message,sizeof(message));
printf_P(PSTR("%lu: APP Received #%u type %c %s from 0%o\n\r"),millis(),header.id,header.type,message.toString(),header.from_node);
// If we get a message, that's a little odd, because this sketch doesn't run on the
// base node. Possibly it's a test message from a child node. Possibly it's a sensor
// calibration message from a parent node.
//
// Either way, it only matters if we're NOT sleeping, and also only useful it we have
// a temp sensor
// If we have a temp sensor AND we are not sleeping
if ( temp_pin > -1 && ( ! Sleep || test_mode ) )
{
// if the received message is a test message, we can respond with a 'C' message in return
if ( header.type == 'c' )
{
// Take a reading
S_message response;
response.temp_reading = measure_temp();
response.voltage_reading = measure_voltage();
// Send it back as a calibration message
RF24NetworkHeader response_header(/*to node*/ header.from_node, /*type*/ 'C');
network.write(response_header,&response,sizeof(response));
}
else if ( header.type == 'C' )
{
// This is a calibration message. Calculate the diff
uint16_t diff = message.temp_reading - measure_temp();
printf_P(PSTR("%lu: APP Calibration received %04x diff %04x\n\r"),millis(),message.temp_reading,diff);
calibration_data.add(diff);
if ( calibration_data.done() )
{
calibration_mode = false;
calibration_leds.disable();
printf_P(PSTR("%lu: APP Stop calibration mode. Calibrate by %04x\n\r"),millis(),calibration_data.result());
// Now apply the calibration
this_node.temp_calibration += calibration_data.result();
// And save it to eeprom...
set_temp_calibration( this_node.temp_calibration );
}
}
}
}
// If we are the kind of node that sends readings,
// AND we have a temp sensor
// AND it's time to send a reading
// AND we're in the mode where we send readings...
if ( this_node.address > 0 && temp_pin > -1 && ( ( Sleep && ! test_mode ) || send_timer.wasFired() ) && ! startup_leds )
{
// Transmission beginning, TX LED ON
Yellow = true;
if ( test_mode && ! calibration_mode )
{
Green = false;
Red = false;
}
S_message message;
message.temp_reading = measure_temp();
message.voltage_reading = measure_voltage();
char message_type = 'S';
if ( calibration_mode )
message_type = 'c';
else if (test_mode )
message_type = 't';
// By default send to the base
uint16_t to_node = 0;
if ( test_mode )
// In test mode, sent to our parent.
to_node = network.parent();
printf_P(PSTR("---------------------------------\n\r"));
printf_P(PSTR("%lu: APP Sending type-%c %s to 0%o...\n\r"),millis(),message_type,message.toString(),to_node);
RF24NetworkHeader header(to_node,message_type);
bool ok = network.write(header,&message,sizeof(message));
if (ok)
{
if ( test_mode && ! calibration_mode )
Green = true;
printf_P(PSTR("%lu: APP Send ok\n\r"),millis());
}
else
{
if ( test_mode && ! calibration_mode )
Red = true;
printf_P(PSTR("%lu: APP Send failed\n\r"),millis());
}
// Transmission complete, TX LED OFF
Yellow = false;
if ( Sleep && ! test_mode )
{
// Power down the radio. Note that the radio will get powered back up
// on the next write() call.
radio.powerDown();
// Be sure to flush the serial first before sleeping, so everything
// gets printed properly
Serial.flush();
// Sleep the MCU. The watchdog timer will awaken in a short while, and
// continue execution here.
Sleep.go();
}
}
// Button
unsigned a = ButtonA.wasReleased();
if ( a && a < 500 )
{
// Pressing the button during startup sequences engages test mode.
// Pressing it after turns off test mode.
if ( startup_leds )
{
test_mode = true;
send_timer.setInterval(1000);
printf_P(PSTR("%lu: APP Start test mode\n\r"),millis());
}
else if ( calibration_mode )
{
calibration_mode = false;
calibration_leds.disable();
printf_P(PSTR("%lu: APP Stop calibration mode\n\r"),millis());
}
else if ( test_mode )
{
test_mode = false;
Green = false;
Red = false;
send_timer.setInterval(8000);
printf_P(PSTR("%lu: APP Stop test mode\n\r"),millis());
}
}
// Long press
if ( ButtonLong.wasPressed() && test_mode )
{
calibration_mode = true;
calibration_leds.reset();
calibration_data = CalibrationData();
printf_P(PSTR("%lu: APP Start calibration mode\n\r"),millis());
}
// Listen for a new node address
nodeconfig_listen();
}
// vim:ai:cin:sts=2 sw=2 ft=cpp

View File

@@ -0,0 +1,55 @@
/*
Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
/**
* @file sleep.cpp
*
* Sleep helpers, definitions
*/
#include "RF24Network_config.h"
#include <avr/sleep.h>
#include "sleep.h"
sleep_c Sleep;
/******************************************************************/
void sleep_c::begin(wdt_prescalar_e prescalar_in,short cycles)
{
sleep_cycles_remaining = cycles;
sleep_cycles_per_transmission = cycles;
uint8_t prescalar = min(9,(uint8_t)prescalar_in);
uint8_t wdtcsr = prescalar & 7;
if ( prescalar & 8 )
wdtcsr |= _BV(WDP3);
MCUSR &= ~_BV(WDRF);
WDTCSR = _BV(WDCE) | _BV(WDE);
WDTCSR = _BV(WDCE) | wdtcsr | _BV(WDIE);
}
/******************************************************************/
void sleep_c::go(void)
{
while( sleep_cycles_remaining-- )
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_mode();
}
sleep_cycles_remaining = sleep_cycles_per_transmission;
}
ISR(WDT_vect) {
}
// vim:ai:cin:sts=2 sw=2 ft=cpp

View File

@@ -0,0 +1,84 @@
/*
Copyright (C) 2011 James Coliz, Jr. <maniacbug@ymail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
/**
* @file sleep.h
*
* Declaration of the sleep_c class.
*/
#ifndef __SLEEP_H__
#define __SLEEP_H__
/**
* Enums for the duration of the watchdog timer
*/
typedef enum { wdt_16ms = 0, wdt_32ms, wdt_64ms, wdt_128ms, wdt_250ms, wdt_500ms, wdt_1s, wdt_2s, wdt_4s, wdt_8s } wdt_prescalar_e;
/**
* Simplified sleeping handler
*/
class sleep_c
{
public:
/**
* Enable the system to be able to sleep
*
* Does not actually do any sleeping.
*
* For example, to do something roughly evert minute, configure
* it like this:
*
* @code
* Sleep.begin(wdt_8s,7);
* @endcode
*
* @param prescalar Duration of the watchdog timer interrupt.
* The system will actually sleep for this long.
* @param cycles Number of times the system will wake up before
* returning from @p go().
*/
void begin(wdt_prescalar_e prescalar,short cycles);
/**
* Go to sleep
*
* This will return after the watchdog has awoken for the number
* of times specified in begin().
*/
void go(void);
/**
* Test whether the node sleeps
*
* @retval true if the node will sleep
*/
operator bool(void) const
{
return sleep_cycles_per_transmission;
}
private:
volatile short sleep_cycles_remaining;
short sleep_cycles_per_transmission;
};
/**
* Singleton instance for general use
*
* @warning: This class is hard-coded to ONLY work with this singleton.
* Any other instances will fail.
*/
extern sleep_c Sleep;
#endif // __SLEEP_H__
// vim:ai:cin:sts=2 sw=2 ft=cpp

View File

@@ -0,0 +1,38 @@
/*
Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
*/
#ifndef __TIMER_H__
#define __TIMER_H__
// STL headers
// C headers
// Framework headers
// Library headers
// Project headers
/**
* Simple timer
*/
struct timer_t
{
unsigned long last;
unsigned long interval;
timer_t(unsigned long _interval): interval(_interval) {}
operator bool(void)
{
unsigned long now = millis();
bool result = now - last >= interval;
if ( result )
last = now;
return result;
}
};
#endif // __TEMPLATE_H__
// vim:cin:ai:sts=2 sw=2 ft=cpp