Skip to content

Commit 562113f

Browse files
committed
Initial commit
0 parents  commit 562113f

File tree

4 files changed

+318
-0
lines changed

4 files changed

+318
-0
lines changed

LICENSE.md

Whitespace-only changes.

NexaCtrl.cpp

+255
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,255 @@
1+
/**
2+
* NexaCtrl Library v.02 - Nexa/HomeEasy control library with absolute dim support.
3+
* Original author of this library is PaulDJohnston (http://jtlog.wordpress.com/)
4+
*
5+
* Version 02 by Carl Gunnarsson - Refactoring and adding support for absolute dimming
6+
*/
7+
8+
#include "NexaCtrl.h"
9+
10+
extern "C" {
11+
// AVR LibC Includes
12+
#include <inttypes.h>
13+
#include <avr/interrupt.h>
14+
}
15+
16+
const int NexaCtrl::kPulseHigh = 275;
17+
const int NexaCtrl::kPulseLow0 = 275;
18+
const int NexaCtrl::kPulseLow1 = 1225;
19+
20+
const int NexaCtrl::kLowPulseLength = 64;
21+
22+
/*
23+
* The actual message is 32 bits of data:
24+
* bits 0-25: the group code - a 26bit number assigned to controllers.
25+
* bit 26: group flag
26+
* bit 27: on/off/dim flag
27+
* bits 28-31: the device code - 4bit number.
28+
* bits 32-35: the dim level - 4bit number.
29+
*/
30+
const int NexaCtrl::kControllerIdOffset = 0;
31+
const int NexaCtrl::kControllerIdLength = 26;
32+
const int NexaCtrl::kGroupFlagOffset = 26;
33+
const int NexaCtrl::kOnFlagOffset = 27;
34+
const int NexaCtrl::kDeviceIdOffset = 28;
35+
const int NexaCtrl::kDeviceIdLength = 4;
36+
const int NexaCtrl::kDimOffset = 32;
37+
const int NexaCtrl::kDimLength = 4;
38+
39+
NexaCtrl::NexaCtrl(unsigned int tx_pin, unsigned int rx_pin, unsigned int led_pin)
40+
{
41+
led_pin_ = led_pin;
42+
pinMode(led_pin_, OUTPUT);
43+
44+
NexaCtrl(tx_pin, rx_pin);
45+
}
46+
47+
NexaCtrl::NexaCtrl(unsigned int tx_pin, unsigned int rx_pin)
48+
{
49+
tx_pin_ = tx_pin;
50+
rx_pin_ = rx_pin;
51+
pinMode(tx_pin_, OUTPUT);
52+
pinMode(rx_pin_, INPUT);
53+
54+
// kLowPulseLength + kDimLength because we need room for dim bits if
55+
// we want to transmit a dim signal
56+
low_pulse_array = (int*)calloc((kLowPulseLength + (2 * kDimLength)), sizeof(int));
57+
}
58+
59+
void NexaCtrl::DeviceOn(unsigned long controller_id, unsigned int device_id)
60+
{
61+
SetControllerBits(controller_id);
62+
SetBit(kGroupFlagOffset, 0);
63+
SetBit(kOnFlagOffset, 1);
64+
SetDeviceBits(device_id);
65+
Transmit(kLowPulseLength);
66+
}
67+
68+
void NexaCtrl::DeviceOff(unsigned long controller_id, unsigned int device_id)
69+
{
70+
SetControllerBits(controller_id);
71+
SetBit(kGroupFlagOffset, 0);
72+
SetBit(kOnFlagOffset, 0);
73+
SetDeviceBits(device_id);
74+
Transmit(kLowPulseLength);
75+
}
76+
77+
void NexaCtrl::DeviceDim(unsigned long controller_id, unsigned int device_id, unsigned int dim_level)
78+
{
79+
SetControllerBits(controller_id);
80+
81+
SetBit(kGroupFlagOffset, 0);
82+
83+
// Specific for dim
84+
low_pulse_array[(kOnFlagOffset*2)] = kPulseLow0;
85+
low_pulse_array[(kOnFlagOffset*2) + 1] = kPulseLow0;
86+
87+
SetDeviceBits(device_id);
88+
89+
bool dim_bits[kDimLength];
90+
itob(dim_bits, dim_level, kDimLength);
91+
92+
int bit;
93+
for (bit = 0; bit<kDimLength; bit++) {
94+
SetBit(kDimOffset+bit, dim_bits[bit]);
95+
}
96+
Transmit(kLowPulseLength + (kDimLength * 2));
97+
}
98+
99+
void NexaCtrl::GroupOn(unsigned long controller_id)
100+
{
101+
unsigned int device_id = 0;
102+
SetControllerBits(controller_id);
103+
SetDeviceBits(device_id);
104+
SetBit(kGroupFlagOffset, 1);
105+
SetBit(kOnFlagOffset, 1);
106+
Transmit(kLowPulseLength);
107+
}
108+
109+
void NexaCtrl::GroupOff(unsigned long controller_id)
110+
{
111+
unsigned int device_id = 0;
112+
SetControllerBits(controller_id);
113+
SetDeviceBits(device_id);
114+
SetBit(kGroupFlagOffset, 1);
115+
SetBit(kOnFlagOffset, 0);
116+
Transmit(kLowPulseLength);
117+
}
118+
119+
// Private methods
120+
void NexaCtrl::SetDeviceBits(unsigned int device_id)
121+
{
122+
bool device[kDeviceIdLength];
123+
unsigned long ldevice_id = device_id;
124+
itob(device, ldevice_id, kDeviceIdLength);
125+
int bit;
126+
for (bit=0; bit < kDeviceIdLength; bit++) {
127+
SetBit(kDeviceIdOffset+bit, device[bit]);
128+
}
129+
}
130+
131+
void NexaCtrl::SetControllerBits(unsigned long controller_id)
132+
{
133+
bool controller[kControllerIdLength];
134+
itob(controller, controller_id, kControllerIdLength);
135+
136+
int bit;
137+
for (bit=0; bit < kControllerIdLength; bit++) {
138+
SetBit(kControllerIdOffset+bit, controller[bit]);
139+
}
140+
}
141+
142+
void NexaCtrl::SetBit(unsigned int bit_index, bool value)
143+
{
144+
// Each actual bit of data is encoded as two bits on the wire...
145+
if (!value) {
146+
// Data 0 = Wire 01
147+
low_pulse_array[(bit_index*2)] = kPulseLow0;
148+
low_pulse_array[(bit_index*2) + 1] = kPulseLow1;
149+
} else {
150+
// Data 1 = Wire 10
151+
low_pulse_array[(bit_index*2)] = kPulseLow1;
152+
low_pulse_array[(bit_index*2) + 1] = kPulseLow0;
153+
}
154+
}
155+
156+
void NexaCtrl::Transmit(int pulse_length)
157+
{
158+
int pulse_count;
159+
int transmit_count;
160+
161+
cli(); // disable interupts
162+
163+
for (transmit_count = 0; transmit_count < 2; transmit_count++)
164+
{
165+
if (led_pin_ > 0) {
166+
digitalWrite(led_pin_, HIGH);
167+
}
168+
TransmitLatch1();
169+
TransmitLatch2();
170+
171+
/*
172+
* Transmit the actual message
173+
* every wire bit starts with the same short high pulse, followed
174+
* by a short or long low pulse from an array of low pulse lengths
175+
*/
176+
for (pulse_count = 0; pulse_count < pulse_length; pulse_count++)
177+
{
178+
digitalWrite(tx_pin_, HIGH);
179+
delayMicroseconds(kPulseHigh);
180+
digitalWrite(tx_pin_, LOW);
181+
delayMicroseconds(low_pulse_array[pulse_count]);
182+
}
183+
184+
TransmitLatch2();
185+
186+
if (led_pin_ > 0) {
187+
digitalWrite(led_pin_, LOW);
188+
}
189+
190+
delayMicroseconds(10000);
191+
}
192+
193+
sei(); // enable interupts
194+
}
195+
196+
void NexaCtrl::TransmitLatch1(void)
197+
{
198+
// bit of radio shouting before we start
199+
digitalWrite(tx_pin_, HIGH);
200+
delayMicroseconds(kPulseLow0);
201+
// low for 9900 for latch 1
202+
digitalWrite(tx_pin_, LOW);
203+
delayMicroseconds(9900);
204+
}
205+
206+
void NexaCtrl::TransmitLatch2(void)
207+
{
208+
// high for a moment 275
209+
digitalWrite(tx_pin_, HIGH);
210+
delayMicroseconds(kPulseLow0);
211+
// low for 2675 for latch 2
212+
digitalWrite(tx_pin_, LOW);
213+
delayMicroseconds(2675);
214+
}
215+
216+
void itob(bool *bits, unsigned long integer, int length) {
217+
for (int i=0; i<length; i++){
218+
if ((integer / power2(length-1-i))==1){
219+
integer-=power2(length-1-i);
220+
bits[i]=1;
221+
}
222+
else bits[i]=0;
223+
}
224+
}
225+
226+
unsigned long power2(int power){ //gives 2 to the (power)
227+
unsigned long integer=1;
228+
for (int i=0; i<power; i++){
229+
integer*=2;
230+
}
231+
return integer;
232+
}
233+
234+
unsigned long htoi (const char *ptr)
235+
{
236+
unsigned long value = 0;
237+
char ch = *ptr;
238+
239+
while (ch == ' ' || ch == '\t') {
240+
ch = *(++ptr);
241+
}
242+
243+
for (;;) {
244+
if (ch >= '0' && ch <= '9') {
245+
value = (value << 4) + (ch - '0');
246+
} else if (ch >= 'A' && ch <= 'F') {
247+
value = (value << 4) + (ch - 'A' + 10);
248+
} else if (ch >= 'a' && ch <= 'f') {
249+
value = (value << 4) + (ch - 'a' + 10);
250+
} else {
251+
return value;
252+
}
253+
ch = *(++ptr);
254+
}
255+
}

NexaCtrl.h

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#ifndef NexaCtrl_h
2+
#define NexaCtrl_h
3+
4+
#include "Arduino.h"
5+
6+
class NexaCtrl
7+
{
8+
public:
9+
NexaCtrl(unsigned int tx_pin, unsigned int rx_pin, unsigned int led_pin);
10+
NexaCtrl(unsigned int tx_pin, unsigned int rx_pin);
11+
12+
void DeviceOn(unsigned long controller_id, unsigned int device_id);
13+
void DeviceOff(unsigned long controller_id, unsigned int device_id);
14+
15+
void DeviceDim(unsigned long controller_id, unsigned int device_id, unsigned int dim_level);
16+
17+
void GroupOn(unsigned long controller_id);
18+
void GroupOff(unsigned long controller_id);
19+
20+
private:
21+
int tx_pin_;
22+
int rx_pin_;
23+
int led_pin_;
24+
unsigned long controller_id_;
25+
26+
int* low_pulse_array;
27+
28+
const static int kPulseHigh;
29+
const static int kPulseLow0;
30+
const static int kPulseLow1;
31+
32+
const static int kLowPulseLength;
33+
34+
const static int kControllerIdOffset;
35+
const static int kControllerIdLength;
36+
const static int kGroupFlagOffset;
37+
const static int kOnFlagOffset;
38+
const static int kDeviceIdOffset;
39+
const static int kDeviceIdLength;
40+
const static int kDimOffset;
41+
const static int kDimLength;
42+
43+
void SetBit(unsigned int bit_index, bool value);
44+
void SetDeviceBits(unsigned int device_id);
45+
void SetControllerBits(unsigned long controller_id);
46+
void SendPair(bool on);
47+
48+
void Transmit(int pulse_length);
49+
void TransmitLatch1(void);
50+
void TransmitLatch2(void);
51+
};
52+
53+
void itob(bool *bits, unsigned long, int length);
54+
unsigned long power2(int power);
55+
56+
#endif /* NexaCtrl_h */

README.mkd

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
NexaCtrl
2+
========
3+
4+
NexaCtrl Library v.02 - Nexa/HomeEasy control library with absolute dim support.
5+
Original author of this library is PaulDJohnston (http://jtlog.wordpress.com/)
6+
7+
Version 02 by Carl Gunnarsson - Refactoring and adding support for absolute dimming.

0 commit comments

Comments
 (0)