-
Notifications
You must be signed in to change notification settings - Fork 0
/
LogicData.h
136 lines (106 loc) · 2.94 KB
/
LogicData.h
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
//////////////////////////////////////////////////////////
//
// LOGICDATA protocol - Used by motorized office furniture from LogicData.
//
// 32-bit words
// Idle line is logic-high (5v)
// MARK is LOW
// SPACE is HIGH
// Speed is 1000bps, or 1 bit per ms
// Start data by sending MARK for 50ms
// Approximately 50ms between words
// First two bits are always(?) 01 (SPACE MARK)
// All observed words start with 010000000110 (0x406; SPACE MARK SPACEx7 MARKx2 SPACE)
#define LOGICDATA_MIN_WINDOW_MS 50 // 500
#define LOGICDATA_MIN_START_BIT 50
#include <stdint.h>
#include "Arduino.h"
typedef uint32_t micros_t;
#define TRACE_HISTORY_MAX 80 // powers-of-two are faster in MOD
#define Q_MAX TRACE_HISTORY_MAX
#define BIG_IDLE (micros_t(-1)) // An eternity
#define IDLE_TIME (micros_t(1)<<16) // if the signal is idle for this long, we consider it an eternity
// Lock guard; cleans up on exit
struct lock {
lock() {
noInterrupts();
}
~lock() {
interrupts();
}
};
//--------------------------------------------------
// queue
//
typedef uint16_t index_t;
struct mque {
// embedded deque; push to head; pop from tail
micros_t trace[Q_MAX];
index_t head = 0;
index_t tail = 0;
index_t next(index_t x);
bool empty();
bool full();
index_t size();
// destructive push; pushes even if full
void push(micros_t t);
// destructive pop; no-op if empty
bool pop(micros_t * t);
// drop elements from the tail of the queue; no range-checking!
void drop(index_t n);
// non-destructive indexed peek
bool peek(index_t index, micros_t * t);
};
// queue
//
//--------------------------------------------------
class LogicData
{
// int rx_pin;
int tx_pin;
bool active = false;
bool pin_idle = false;
micros_t timer; // calculated time of previous step-end
micros_t start; // time of Open()
mque q;
micros_t prev_bit = 0;
public:
enum { SPACE=0, MARK=1 };
LogicData(int tx) : tx_pin(tx) {}
bool is_active() { return active; }
void Begin();
// Receive
void PinChange(bool level);
void Service();
uint32_t ReadTrace();
// Calculate parity and set in lsb of message
static uint32_t Parity(uint32_t msg);
static bool CheckParity(uint32_t msg);
static const char * MsgType(uint32_t msg);
static const char * Decode(uint32_t msg);
bool IsValid(uint32_t msg);
bool IsNumber(uint32_t msg);
uint8_t GetNumber(uint32_t msg);
// debug: not threadsafe
index_t QueueSize(index_t &h, index_t &t){
lock _;
h = q.head;
t = q.tail;
return q.size();
}
// Transmit
void SendBit(bool bit);
void MicroDelay(micros_t us);
void Delay(uint16_t ms);
void SendBit(bool bit, uint16_t ms);
void Space(uint16_t ms=LOGICDATA_MIN_START_BIT);
void SendStartBit();
void Stop();
void Send(uint32_t data);
void OpenChannel();
void CloseChannel();
void Send(uint32_t * data, unsigned count);
};
//
// LOGICDATA protocol
//////////////////////////////////////////////////////////