AllWize Library
RC1701XX_Mockup.h
Go to the documentation of this file.
1 /*
2 
3 RC1701XX module mockup
4 
5 Copyright (C) 2016-2018 by Xose PĂ©rez <xose dot perez at gmail dot com>
6 
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 
20 */
21 
22 #pragma once
23 
24 #include <stdlib.h>
25 #include <Stream.h>
26 
27 #define MOCKUP_RESPONSE_BYTE 0xA0
28 #define MOCKUP_DEBUG 0
29 #define MOCKUP_BUFFER_SIZE 128
30 
32 
33  public:
34 
35  CircularBuffer(uint8_t size = 128) : _size(size) {
36  _buffer = new char[size];
37  }
38 
39  virtual ~CircularBuffer() {
40  delete[] _buffer;
41  }
42 
43  virtual void flush() {
44  _read = _write = 0;
45  }
46 
47  virtual uint8_t available() {
48  if (_write >= _read) return _write - _read;
49  return _size - _read + _write;
50  }
51 
52  virtual int write(char ch) {
53  _buffer[_write] = ch;
54  _write = (_write + 1) % _size;
55  return 1;
56  }
57 
58  virtual int read() {
59  if (_write == _read) return -1;
60  uint8_t ch = _buffer[_read];
61  _read = (_read + 1) % _size;
62  return ch;
63  }
64 
65  virtual int peek() {
66  if (_write == _read) return -1;
67  return (uint8_t) _buffer[_read];
68  }
69 
70  private:
71  char * _buffer;
72  uint8_t _size;
73  uint8_t _read;
74  uint8_t _write;
75 
76 };
77 
78 class RC1701XX_Mockup : public Stream {
79 
80  public:
81 
82  // ---------------------------------------------------------------------
83  // Constructor & destructor
84  // ---------------------------------------------------------------------
85 
89  }
90 
91  virtual ~RC1701XX_Mockup() {
92  delete _rx;
93  delete _tx;
94  }
95 
96  virtual void reset() {
97  _pending_payload = 0;
99  _config_mode = false;
100  _memory_mode = false;
101  _command_mode = false;
102  _rx->flush();
103  _tx->flush();
104  }
105 
106  // ---------------------------------------------------------------------
107  // Stream interface
108  // ---------------------------------------------------------------------
109 
110  virtual size_t write(uint8_t ch) {
111 
112  #if MOCKUP_DEBUG
113  SerialUSB.print("Received: 0x");
114  SerialUSB.println((uint8_t) ch, HEX);
115  #endif
116 
117  _process(ch);
118  return _rx->write(ch);
119 
120  }
121 
122  virtual int read() {
123  return _tx->read();
124  }
125 
126  virtual int available() {
127  return _tx->available();
128  }
129 
130  virtual int peek() {
131  return _tx->peek();
132  }
133 
134  virtual void flush() {
135  _tx->flush();
136  }
137 
138  // ---------------------------------------------------------------------
139  // Inverted stream
140  // ---------------------------------------------------------------------
141 
142  virtual size_t rx_write(uint8_t ch) {
143 
144  #if MOCKUP_DEBUG
145  SerialUSB.print("Sending : 0x");
146  SerialUSB.println((uint8_t) ch, HEX);
147  #endif
148 
149  return _tx->write(ch);
150 
151  }
152 
153  virtual int rx_read() {
154  return _rx->read();
155  }
156 
157  virtual int rx_available() {
158  return _rx->available();
159  }
160 
161  virtual void rx_flush() {
162  _rx->flush();
163  }
164 
165  private:
166 
167  // ---------------------------------------------------------------------
168  // Data processing
169  // ---------------------------------------------------------------------
170 
171  void _process(uint8_t ch) {
172 
173  // Expected payload sizes (defaults to 1 byte)
174  if (0 == _pending_payload) {
175 
176  // Check config mode
177  if (!_config_mode & (0x00 == ch)) _config_mode = true;
178  if (_config_mode & (0x58 == ch)) _config_mode = false;
179  if (!_config_mode) return;
180  if (_command_mode) return;
181 
182  // Memory mode
183  if (_memory_mode) {
184  if (0xFF == ch) {
185  _memory_mode = false;
186  rx_write('>');
187  } else {
188  _pending_payload = 1;
189  }
190  return;
191  }
192 
193  // Handle cases
194  switch (ch) {
195 
196  case 0x00:
197  _pending_payload = 0;
198  break;
199 
200  case '@':
201  _command_mode = true;
202  return;
203 
204  case 'A':
205  _pending_payload = 2;
206  break;
207 
208  case 'B':
209  _pending_payload = 8;
210  break;
211 
212  case 'K':
213  _pending_payload = 17;
214  break;
215 
216  case 'L':
217  _pending_payload = 1;
218  _pending_response = 8;
219  break;
220 
221  case 'M':
222  _memory_mode = true;
223  _pending_payload = 2;
224  break;
225 
226  case 'O':
227  _pending_payload = 1;
228  _pending_response = 2;
229  break;
230 
231  case 'Q':
232  case 'S':
233  case 'U':
234  case 'V':
235  _pending_payload = 0;
237  break;
238 
239  case 'T':
240  _pending_payload = 8;
241  break;
242 
243  case 'W':
244  // TODO
245  break;
246 
247  case 'Y':
248  _pending_payload = 1;
249  _pending_response = 1;
250  break;
251 
252  default:
253  _pending_payload = 1;
254  break;
255 
256  }
257 
258  // Show prompt
259  rx_write('>');
260 
261  } else {
262 
263  // Update pending payload
265 
266  // Memory mode
267  if (_memory_mode || _command_mode) return;
268 
269  // If no more payload
270  if (0 == _pending_payload) {
271 
272  // Inject response
273  for (uint8_t i=0; i<_pending_response; i++) {
275  }
276 
277  // Reset response size
278  _pending_response = 0;
279 
280  // Show prompt
281  rx_write('>');
282 
283  }
284 
285  }
286  }
287 
288  CircularBuffer * _rx; // Chars sent to the module (using write)
289  CircularBuffer * _tx; // Chars sent by the module (read-able)
290 
291  uint8_t _pending_payload = 0;
292  uint8_t _pending_response = 0;
293  bool _config_mode = false;
294  bool _memory_mode = false;
295  bool _command_mode = false;
296 
297 };
virtual int rx_available()
virtual uint8_t available()
virtual int rx_read()
virtual int read()
virtual void flush()
virtual size_t write(uint8_t ch)
virtual int write(char ch)
virtual size_t rx_write(uint8_t ch)
virtual int available()
virtual void rx_flush()
void _process(uint8_t ch)
CircularBuffer(uint8_t size=128)
uint8_t _pending_response
#define MOCKUP_BUFFER_SIZE
CircularBuffer * _tx
virtual int read()
#define MOCKUP_RESPONSE_BYTE
uint8_t _pending_payload
virtual ~RC1701XX_Mockup()
virtual void reset()
virtual int peek()
CircularBuffer * _rx
virtual void flush()
virtual ~CircularBuffer()
virtual int peek()