-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathS0Impulse.h
More file actions
283 lines (220 loc) · 6.12 KB
/
Copy pathS0Impulse.h
File metadata and controls
283 lines (220 loc) · 6.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
#include <Arduino.h>
// #include <EEPROM.h>
#include <avr/eeprom.h>
#define S0_ADDR(A) ((EEPROM_S0_OFFSET) + ((id) * (EEPROM_S0_SIZE)) + (A))
/*
EEPROM
Size Name
2 Use DHCP
4 IP
4 Netmask
4 Broadcast Address
16 S0 name
2 Impulses per kWh
2 Active
2 Delta before send base
2 Delta before send factor
2 Recurring sending interval base
2 Recurring sending interval factor
2
2
*/
#define EEPROM_S0_OFFSET 32
#define EEPROM_S0_SIZE 32
#define EEPROM_S0_FLAGS 0 // Bitvalues see below
#define EEPROM_S0_CNT_PER_KWH 2
#define EEPROM_S0_DELTA_BASE 4
#define EEPROM_S0_DELTA_FACTOR 6
#define EEPROM_S0_TIME_BASE 8
#define EEPROM_S0_TIME_FACTOR 10
#define EEPROM_S0_1 12
#define EEPROM_S0_2 14
#define EEPROM_S0_NAME 16
#define EEPROM_S0_NAME_LENGTH 15
#define EEPROM_S0_FLAG_ACTIVE 0
#define EEPROM_S0_FLAG_UPDATE_VALUE_DELTA 1
#define EEPROM_S0_FLAG_UPDATE_TIME_DELTA 2
#define EEPROM_S0_FLAG_SEND_DELTA 3
// To use the library, define a class that subclasses CallBackInterface.
// And also, include a method (C++ talk for "subroutine") called "cbmethod()" in the class.
// Use this class as a template to create your own; it's not hard. You don't
// even have to understand what you're doing at first.
// How do you subclass? Like this:
class S0Impulse : public CallBackInterface
{
public:
uint16_t countHigh;
uint16_t countLow;
uint16_t countLowPerHigh;
uint32_t count;
uint16_t deltaBase;
uint16_t deltaFactor;
uint32_t delta;
uint32_t reqNextUpdate;
uint16_t timeBase;
uint16_t timeFactor;
uint32_t updateInterval;
uint8_t pin;
uint8_t id;
uint8_t flags;
uint8_t isActive;
uint8_t reqDeltaUpdate;
uint8_t reqTimeUpdate;
uint8_t * requestUpdatePtr;
S0Impulse(void)
{
};
#if 0
S0Impulse(uint8_t _pin, uint16_t _countLowPerHigh):
pin(_pin),
countLowPerHigh(_countLowPerHigh)
{
init();
};
#endif
S0Impulse(uint8_t _pin, uint8_t _id):
pin(_pin),
id(_id)
{
initFromEEPROM();
};
S0Impulse(uint8_t _pin, uint16_t _countLowPerHigh, uint8_t _id):
pin(_pin),
countLowPerHigh(_countLowPerHigh),
id(_id)
{
init();
};
// this gets called on a pin change event on pin "pin"
// Increment low count. on overflow increment high count and reset low count.
void cbmethod()
{
countLow ++;
if (countLow >= countLowPerHigh)
{
countHigh ++;
countLow = 0;
}
};
uint16_t getCountLow()
{
return countLow;
}
uint16_t getCountHigh()
{
return countHigh;
}
uint16_t getCountLowPerHigh()
{
return countLowPerHigh;
}
uint16_t setCountLowPerHigh(uint16_t _countLowPerHigh)
{
eeprom_write_word((uint16_t *)S0_ADDR(EEPROM_S0_CNT_PER_KWH), _countLowPerHigh);
return countLowPerHigh = _countLowPerHigh;
}
float getCount()
{
// Disable interrupts - Prevent updates during calculations leading to loosing ticks
// Disable interrupts as short as possible
noInterrupts();
// Make local copies of counters to work with
uint16_t _high = countHigh;
uint16_t _low = countLow;
// Resume interrupts again
interrupts();
float f = (float) _high + (float) _low / (float) countLowPerHigh;
return f;
}
float getCountClear()
{
// Disable interrupts - Prevent updates during calculations leading to loosing ticks
// Disable interrupts as short as possible
noInterrupts();
// Make local copies of counters to work with
uint16_t _high = countHigh;
uint16_t _low = countLow;
// Clear counters
countLow = countHigh = 0;
// Resume interrupts again
interrupts();
float f = (float) _high + (float) _low / (float) countLowPerHigh;
return f;
}
uint8_t getPin()
{
return pin;
}
uint8_t getID()
{
return id;
}
uint8_t setID(uint8_t _id)
{
return id = _id;
}
uint8_t getIsActive ()
{
return isActive;
}
uint8_t setActive()
{
if (isActive)
return isActive;
isActive = 1;
flags |= (1 << EEPROM_S0_FLAG_ACTIVE);
eeprom_write_word((uint16_t *)S0_ADDR(EEPROM_S0_FLAGS), flags);
return isActive;
}
uint8_t setInactive()
{
if (! isActive)
return isActive;
isActive = 0;
flags &= ~(1 << EEPROM_S0_FLAG_ACTIVE);
eeprom_write_word((uint16_t *)S0_ADDR(EEPROM_S0_FLAGS), flags);
return isActive;
}
void reset()
{
countLow = countHigh = 0;
}
void setName(const char * _cp)
{
uint8_t nameLength = strlen(_cp);
if (nameLength > EEPROM_S0_NAME_LENGTH)
nameLength = EEPROM_S0_NAME_LENGTH;
eeprom_write_block(_cp, (void *)S0_ADDR(EEPROM_S0_NAME), nameLength);
eeprom_write_byte((uint8_t *)S0_ADDR(EEPROM_S0_NAME + nameLength), 0);
return;
}
private:
void init ()
{
pinMode(pin, INPUT);
digitalWrite(pin, HIGH);
PCintPort::attachInterrupt(pin, this, FALLING);
countLow = countHigh = 0;
isActive = 0;
}
void initFromEEPROM()
{
pinMode(pin, INPUT);
digitalWrite(pin, HIGH);
PCintPort::attachInterrupt(pin, this, FALLING);
countLow = countHigh = 0;
// Flags
flags = eeprom_read_byte((uint8_t *)S0_ADDR(EEPROM_S0_FLAGS));
isActive = flags & (1 << EEPROM_S0_FLAG_ACTIVE);
reqDeltaUpdate = flags & (1 << EEPROM_S0_FLAG_UPDATE_VALUE_DELTA);
reqTimeUpdate = flags & (1 << EEPROM_S0_FLAG_UPDATE_TIME_DELTA);
// countLowPerHigh
countLowPerHigh = eeprom_read_word((uint16_t *)S0_ADDR(EEPROM_S0_CNT_PER_KWH));
// delta values
deltaBase = eeprom_read_word((uint16_t *)S0_ADDR(EEPROM_S0_DELTA_BASE));
deltaFactor = eeprom_read_word((uint16_t *)S0_ADDR(EEPROM_S0_DELTA_FACTOR));
// time values
timeBase = eeprom_read_word((uint16_t *)S0_ADDR(EEPROM_S0_TIME_BASE));
timeFactor = eeprom_read_word((uint16_t *)S0_ADDR(EEPROM_S0_TIME_FACTOR));
}
};