Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 627 lines (550 sloc) 22.562 kB
96f3ef8 initial commit
Railstars authored
1 #include "DCCPacketScheduler.h"
2
3 /*
4 * DCC Waveform Generator
5 *
6 *
7 * Hardware requirements:
8 * *A DCC booster with Rail A and Rail B wired to pin 9 and 10 respectively.
9 * *A locomotive with a decoder installed, reset to factory defaults.
10 *
11 * Author: Don Goodman-Wilson dgoodman@artificial-science.org
12 *
13 * based on software by Wolfgang Kufer, http://opendcc.de
14 *
15 * Copyright 2010 Don Goodman-Wilson
16 * This program is free software: you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation, either version 3 of the License, or
19 * at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28 *
29 */
30
31 /// An enumerated type for keeping track of the state machine used in the timer1 ISR
32 /** Given the structure of a DCC packet, the ISR can be in one of 5 states.
33 *dos_idle: there is nothing to put on the rails. In this case, the only legal thing
34 to do is to put a '1' on the rails. The ISR should almost never be in this state.
35 *dos_send_premable: A packet has been made available, and so we should broadcast the preamble: 14 '1's in a row
36 *dos_send_bstart: Each data byte is preceded by a '0'
37 *dos_send_byte: Sending the current data byte
38 *dos_end_bit: After the final byte is sent, send a '0'.
39 */
40 enum DCC_output_state_t {
41 dos_idle,
42 dos_send_preamble,
43 dos_send_bstart,
44 dos_send_byte,
45 dos_end_bit
46 };
47
48 DCC_output_state_t DCC_state = dos_idle; //just to start out
49
50 /// The currently queued packet to be put on the rails. Default is a reset packet.
51 byte current_packet[6] = {0,0,0,0,0,0};
52 /// How many data bytes in the queued packet?
88a0ba7 Tons of run-time bug fixes. Should maybe work now?
Railstars authored
53 volatile byte current_packet_size = 0;
96f3ef8 initial commit
Railstars authored
54 /// How many bytes remain to be put on the rails?
88a0ba7 Tons of run-time bug fixes. Should maybe work now?
Railstars authored
55 volatile byte current_byte_counter = 0;
96f3ef8 initial commit
Railstars authored
56 /// How many bits remain in the current data byte/preamble before changing states?
57 volatile byte current_bit_counter = 14; //init to 14 1's for the preamble
58 /// A fixed-content packet to send when idle
59 //byte DCC_Idle_Packet[3] = {255,0,255};
60 /// A fixed-content packet to send to reset all decoders on layout
61 //byte DCC_Reset_Packet[3] = {0,0,0};
62
63
64 /// Timer1 TOP values for one and zero
65 /** S 9.1 A specifies that '1's are represented by a square wave with a half-period of 58us (valid range: 55-61us)
66 and '0's with a half-period of >100us (valid range: 95-9900us)
67 Because '0's are stretched to provide DC power to non-DCC locos, we need two zero counters,
68 one for the top half, and one for the bottom half.
69
70 Here is how to calculate the timer1 counter values (from ATMega168 datasheet, 15.9.2):
f2563b2 Added compatbility with the AT90CAN128/64/32 MCUs, and fixed a linger…
Railstars authored
71 f_{OC1A} = \frac{f_{clk_I/O}}{2*N*(1+OCR1A)})
72 where N = prescalar, and OCR1A is the TOP we need to calculate.
96f3ef8 initial commit
Railstars authored
73 We know the desired half period for each case, 58us and >100us.
74 So:
75 for ones:
f2563b2 Added compatbility with the AT90CAN128/64/32 MCUs, and fixed a linger…
Railstars authored
76 58us = (8*(1+OCR1A)) / (16MHz)
77 58us * 16MHz = 8*(1+OCR1A)
78 58us * 2MHz = 1+OCR1A
96f3ef8 initial commit
Railstars authored
79 OCR1A = 115
80
81 for zeros:
f2563b2 Added compatbility with the AT90CAN128/64/32 MCUs, and fixed a linger…
Railstars authored
82 100us * 2MHz = 1+OCR1A
83 OCR1A = 199
84
85 Thus, we also know that the valid range for stretched-zero operation is something like this:
86 9900us = (8*(1+OCR1A)) / (16MHz)
87 9900us * 2MHz = 1+OCR1A
88 OCR1A = 19799
89
96f3ef8 initial commit
Railstars authored
90 */
f2563b2 Added compatbility with the AT90CAN128/64/32 MCUs, and fixed a linger…
Railstars authored
91
96f3ef8 initial commit
Railstars authored
92 unsigned int one_count=115; //58us
93 unsigned int zero_high_count=199; //100us
94 unsigned int zero_low_count=199; //100us
95
3138243 Filled in method for ops mode programming of multi-function (loco) de…
Railstars authored
96 /// Setup phase: configure and enable timer1 CTC interrupt, set OC1A and OC1B to toggle on CTC
96f3ef8 initial commit
Railstars authored
97 void setup_DCC_waveform_generator() {
98
f2563b2 Added compatbility with the AT90CAN128/64/32 MCUs, and fixed a linger…
Railstars authored
99 //Set the OC1A and OC1B pins (Timer1 output pins A and B) to output mode
100 //On Arduino UNO, etc, OC1A is Port B/Pin 1 and OC1B Port B/Pin 2
101 //On Arduino MEGA, etc, OC1A is or Port B/Pin 5 and OC1B Port B/Pin 6
102 #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90CAN128__) || defined(__AVR_AT90CAN64__) || defined(__AVR_AT90CAN32__)
103 DDRB |= (1<<DDB5) | (1<<DDB6);
6274268 Added tentative support for Arduino MEGA
Railstars authored
104 #else
f2563b2 Added compatbility with the AT90CAN128/64/32 MCUs, and fixed a linger…
Railstars authored
105 DDRB |= (1<<DDB1) | (1<<DDB2);
6274268 Added tentative support for Arduino MEGA
Railstars authored
106 #endif
96f3ef8 initial commit
Railstars authored
107
108 // Configure timer1 in CTC mode, for waveform generation, set to toggle OC1A, OC1B, at /8 prescalar, interupt at CTC
f2563b2 Added compatbility with the AT90CAN128/64/32 MCUs, and fixed a linger…
Railstars authored
109 TCCR1A = (0<<COM1A1) | (1<<COM1A0) | (0<<COM1B1) | (1<<COM1B0) | (0<<WGM11) | (0<<WGM10);
96f3ef8 initial commit
Railstars authored
110 TCCR1B = (0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (1<<WGM12) | (0<<CS12) | (1<<CS11) | (0<<CS10);
111
112 // start by outputting a '1'
f2563b2 Added compatbility with the AT90CAN128/64/32 MCUs, and fixed a linger…
Railstars authored
113 OCR1A = OCR1B = one_count; //Whenever we set OCR1A, we must also set OCR1B, or else pin OC1B will get out of sync with OC1A!
114 TCNT1 = 0; //get the timer rolling (not really necessary? defaults to 0. Just in case.)
705bef6 Fixed a major bug were packets were being terribly corrupted! Idle pa…
Railstars authored
115
f2563b2 Added compatbility with the AT90CAN128/64/32 MCUs, and fixed a linger…
Railstars authored
116 //finally, force a toggle on OC1B so that pin OC1B will always complement pin OC1A
117 TCCR1C |= (1<<FOC1B);
118
96f3ef8 initial commit
Railstars authored
119 }
120
705bef6 Fixed a major bug were packets were being terribly corrupted! Idle pa…
Railstars authored
121 void DCC_waveform_generation_hasshin()
122 {
123 //enable the compare match interrupt
124 TIMSK1 |= (1<<OCIE1A);
125 }
126
96f3ef8 initial commit
Railstars authored
127 /// This is the Interrupt Service Routine (ISR) for Timer1 compare match.
128 ISR(TIMER1_COMPA_vect)
129 {
130 //in CTC mode, timer TCINT1 automatically resets to 0 when it matches OCR1A. Depending on the next bit to output,
131 //we may have to alter the value in OCR1A, maybe.
132 //to switch between "one" waveform and "zero" waveform, we assign a value to OCR1A.
133
134 //remember, anything we set for OCR1A takes effect IMMEDIATELY, so we are working within the cycle we are setting.
135 //first, check to see if we're in the second half of a byte; only act on the first half of a byte
6274268 Added tentative support for Arduino MEGA
Railstars authored
136 //On Arduino UNO, etc, OC1A is digital pin 9, or Port B/Pin 1
137 //On Arduino MEGA, etc, OC1A is digital pin 11, or Port B/Pin 5
f2563b2 Added compatbility with the AT90CAN128/64/32 MCUs, and fixed a linger…
Railstars authored
138 #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90CAN128__) || defined(__AVR_AT90CAN64__) || defined(__AVR_AT90CAN32__)
139 if(PINB & (1<<PINB6)) //if the pin is low, we need to use a different zero counter to enable streched-zero DC operation
6274268 Added tentative support for Arduino MEGA
Railstars authored
140 #else
f2563b2 Added compatbility with the AT90CAN128/64/32 MCUs, and fixed a linger…
Railstars authored
141 if(PINB & (1<<PINB1)) //if the pin is low, we need to use a different zero counter to enable streched-zero DC operation
6274268 Added tentative support for Arduino MEGA
Railstars authored
142 #endif
f2563b2 Added compatbility with the AT90CAN128/64/32 MCUs, and fixed a linger…
Railstars authored
143
96f3ef8 initial commit
Railstars authored
144 {
1afa334 bug fixes, fleshed out the setSpeed128 function and the repeatPacket …
Railstars authored
145 if(OCR1A == zero_high_count) //if the pin is low and outputting a zero, we need to be using zero_low_count
96f3ef8 initial commit
Railstars authored
146 {
f2563b2 Added compatbility with the AT90CAN128/64/32 MCUs, and fixed a linger…
Railstars authored
147 OCR1A = OCR1B = zero_low_count;
96f3ef8 initial commit
Railstars authored
148 }
149 }
1afa334 bug fixes, fleshed out the setSpeed128 function and the repeatPacket …
Railstars authored
150 else //the pin is high. New cycle is begining. Here's where the real work goes.
96f3ef8 initial commit
Railstars authored
151 {
152 //time to switch things up, maybe. send the current bit in the current packet.
153 //if this is the last bit to send, queue up another packet (might be the idle packet).
154 switch(DCC_state)
155 {
156 /// Idle: Check if a new packet is ready. If it is, fall through to dos_send_premable. Otherwise just stick a '1' out there.
157 case dos_idle:
158 if(!current_byte_counter) //if no new packet
159 {
705bef6 Fixed a major bug were packets were being terribly corrupted! Idle pa…
Railstars authored
160 // Serial.println("X");
f2563b2 Added compatbility with the AT90CAN128/64/32 MCUs, and fixed a linger…
Railstars authored
161 OCR1A = OCR1B = one_count; //just send ones if we don't know what else to do. safe bet.
96f3ef8 initial commit
Railstars authored
162 break;
163 }
6c87238 Added debugging message to figure out why MEGAs seem to only ever wri…
Railstars authored
164 //looks like there's a new packet for us to dump on the wire!
165 //for debugging purposes, let's print it out
de74490 Fixed an issue where, basically, setting functions 0-8 using one of t…
Railstars authored
166 // if(current_packet[1] != 0xFF)
167 // {
705bef6 Fixed a major bug were packets were being terribly corrupted! Idle pa…
Railstars authored
168 // Serial.print("Packet: ");
de74490 Fixed an issue where, basically, setting functions 0-8 using one of t…
Railstars authored
169 // for(byte j = 0; j < current_packet_size; ++j)
170 // {
171 // Serial.print(current_packet[j],HEX);
172 // Serial.print(" ");
173 // }
174 // Serial.println("");
175 // }
96f3ef8 initial commit
Railstars authored
176 DCC_state = dos_send_preamble; //and fall through to dos_send_preamble
177 /// Preamble: In the process of producing 14 '1's, counter by current_bit_counter; when complete, move to dos_send_bstart
178 case dos_send_preamble:
f2563b2 Added compatbility with the AT90CAN128/64/32 MCUs, and fixed a linger…
Railstars authored
179 OCR1A = OCR1B = one_count;
705bef6 Fixed a major bug were packets were being terribly corrupted! Idle pa…
Railstars authored
180 // Serial.print("P");
96f3ef8 initial commit
Railstars authored
181 if(!--current_bit_counter)
182 DCC_state = dos_send_bstart;
183 break;
184 /// About to send a data byte, but have to peceed the data with a '0'. Send that '0', then move to dos_send_byte
185 case dos_send_bstart:
f2563b2 Added compatbility with the AT90CAN128/64/32 MCUs, and fixed a linger…
Railstars authored
186 OCR1A = OCR1B = zero_high_count;
96f3ef8 initial commit
Railstars authored
187 DCC_state = dos_send_byte;
188 current_bit_counter = 8;
705bef6 Fixed a major bug were packets were being terribly corrupted! Idle pa…
Railstars authored
189 // Serial.print(" 0 ");
96f3ef8 initial commit
Railstars authored
190 break;
191 /// Sending a data byte; current bit is tracked with current_bit_counter, and current byte with current_byte_counter
192 case dos_send_byte:
193 if(((current_packet[current_packet_size-current_byte_counter])>>(current_bit_counter-1)) & 1) //is current bit a '1'?
194 {
f2563b2 Added compatbility with the AT90CAN128/64/32 MCUs, and fixed a linger…
Railstars authored
195 OCR1A = OCR1B = one_count;
705bef6 Fixed a major bug were packets were being terribly corrupted! Idle pa…
Railstars authored
196 // Serial.print("1");
96f3ef8 initial commit
Railstars authored
197 }
198 else //or is it a '0'
199 {
f2563b2 Added compatbility with the AT90CAN128/64/32 MCUs, and fixed a linger…
Railstars authored
200 OCR1A = OCR1B = zero_high_count;
705bef6 Fixed a major bug were packets were being terribly corrupted! Idle pa…
Railstars authored
201 // Serial.print("0");
96f3ef8 initial commit
Railstars authored
202 }
203 if(!--current_bit_counter) //out of bits! time to either send a new byte, or end the packet
204 {
205 if(!--current_byte_counter) //if not more bytes, move to dos_end_bit
206 {
207 DCC_state = dos_end_bit;
208 }
209 else //there are more bytes…so, go back to dos_send_bstart
210 {
211 DCC_state = dos_send_bstart;
212 }
213 }
214 break;
215 /// Done with the packet. Send out a final '1', then head back to dos_idle to check for a new packet.
216 case dos_end_bit:
f2563b2 Added compatbility with the AT90CAN128/64/32 MCUs, and fixed a linger…
Railstars authored
217 OCR1A = OCR1B = one_count;
96f3ef8 initial commit
Railstars authored
218 DCC_state = dos_idle;
219 current_bit_counter = 14; //in preparation for a premable...
705bef6 Fixed a major bug were packets were being terribly corrupted! Idle pa…
Railstars authored
220 // Serial.println(" 1");
96f3ef8 initial commit
Railstars authored
221 break;
222 }
223 }
224 }
225
226 ///////////////////////////////////////////////
227 ///////////////////////////////////////////////
228 ///////////////////////////////////////////////
229
88a0ba7 Tons of run-time bug fixes. Should maybe work now?
Railstars authored
230 DCCPacketScheduler::DCCPacketScheduler(void) : packet_counter(1), default_speed_steps(128), last_packet_address(255)
96f3ef8 initial commit
Railstars authored
231 {
88a0ba7 Tons of run-time bug fixes. Should maybe work now?
Railstars authored
232 e_stop_queue.setup(E_STOP_QUEUE_SIZE);
233 high_priority_queue.setup(HIGH_PRIORITY_QUEUE_SIZE);
234 low_priority_queue.setup(LOW_PRIORITY_QUEUE_SIZE);
235 repeat_queue.setup(REPEAT_QUEUE_SIZE);
6c5699b Shaved down on some of the classes to reduce memory footprint; Total …
Railstars authored
236 //periodic_refresh_queue.setup(PERIODIC_REFRESH_QUEUE_SIZE);
96f3ef8 initial commit
Railstars authored
237 }
238
239 //for configuration
538dbdb Bugfixes to get it to compile.
Railstars authored
240 void DCCPacketScheduler::setDefaultSpeedSteps(byte new_speed_steps)
96f3ef8 initial commit
Railstars authored
241 {
242 default_speed_steps = new_speed_steps;
243 }
244
245 void DCCPacketScheduler::setup(void) //for any post-constructor initialization
246 {
247 setup_DCC_waveform_generator();
243fb8b added layout initialisation as per RP 9.2.4, plus bug fixes
Railstars authored
248
6c604b0 Not sure that the estop queue is working yet. Also not sure that setu…
Railstars authored
249 //TODO ELIMINATE THE JERKY START! WHAT'S GOING ON!?
250
243fb8b added layout initialisation as per RP 9.2.4, plus bug fixes
Railstars authored
251 //Following RP 9.2.4, begin by putting 20 reset packets and 10 idle packets on the rails.
252 //use the e_stop_queue to do this, to ensure these packets go out first!
6c604b0 Not sure that the estop queue is working yet. Also not sure that setu…
Railstars authored
253
243fb8b added layout initialisation as per RP 9.2.4, plus bug fixes
Railstars authored
254
255 DCCPacket p;
b668481 Fixed DCCPacketScheduler::setup() to generate valid idle packets. Fix…
Railstars authored
256 byte data[] = {0x00};
243fb8b added layout initialisation as per RP 9.2.4, plus bug fixes
Railstars authored
257
b668481 Fixed DCCPacketScheduler::setup() to generate valid idle packets. Fix…
Railstars authored
258 //reset packet: address 0x00, data 0x00, XOR 0x00; S 9.2 line 75
243fb8b added layout initialisation as per RP 9.2.4, plus bug fixes
Railstars authored
259 p.addData(data,1);
b668481 Fixed DCCPacketScheduler::setup() to generate valid idle packets. Fix…
Railstars authored
260 p.setAddress(0x00);
243fb8b added layout initialisation as per RP 9.2.4, plus bug fixes
Railstars authored
261 p.setRepeat(20);
88a0ba7 Tons of run-time bug fixes. Should maybe work now?
Railstars authored
262 p.setKind(reset_packet_kind);
5bb7c7f Accidentally commented out code to send layout initialization as per …
Railstars authored
263 e_stop_queue.insertPacket(&p);
243fb8b added layout initialisation as per RP 9.2.4, plus bug fixes
Railstars authored
264
705bef6 Fixed a major bug were packets were being terribly corrupted! Idle pa…
Railstars authored
265 //WHy in the world is it that what gets put on the rails is 4 reset packets, followed by
266 //10 god know's what, followed by something else?
267 // C0 FF 00 FF
268 // 00 FF FF what are these?
269
b668481 Fixed DCCPacketScheduler::setup() to generate valid idle packets. Fix…
Railstars authored
270 //idle packet: address 0xFF, data 0x00, XOR 0xFF; S 9.2 line 90
271 p.setAddress(0xFF);
243fb8b added layout initialisation as per RP 9.2.4, plus bug fixes
Railstars authored
272 p.setRepeat(10);
88a0ba7 Tons of run-time bug fixes. Should maybe work now?
Railstars authored
273 p.setKind(idle_packet_kind);
5bb7c7f Accidentally commented out code to send layout initialization as per …
Railstars authored
274 e_stop_queue.insertPacket(&p); //e_stop_queue will be empty, so no need to check if insertion was OK.
705bef6 Fixed a major bug were packets were being terribly corrupted! Idle pa…
Railstars authored
275
96f3ef8 initial commit
Railstars authored
276 }
277
1afa334 bug fixes, fleshed out the setSpeed128 function and the repeatPacket …
Railstars authored
278 //helper functions
279 void DCCPacketScheduler::repeatPacket(DCCPacket *p)
280 {
538dbdb Bugfixes to get it to compile.
Railstars authored
281 switch(p->getKind())
96f3ef8 initial commit
Railstars authored
282 {
88a0ba7 Tons of run-time bug fixes. Should maybe work now?
Railstars authored
283 case idle_packet_kind:
284 case e_stop_packet_kind: //e_stop packets automatically repeat without having to be put in a special queue
285 break;
1afa334 bug fixes, fleshed out the setSpeed128 function and the repeatPacket …
Railstars authored
286 case speed_packet_kind: //speed packets go to the periodic_refresh queue
6c5699b Shaved down on some of the classes to reduce memory footprint; Total …
Railstars authored
287 // periodic_refresh_queue.insertPacket(p);
288 // break;
de74490 Fixed an issue where, basically, setting functions 0-8 using one of t…
Railstars authored
289 case function_packet_1_kind: //all other packets go to the repeat_queue
290 case function_packet_2_kind: //all other packets go to the repeat_queue
291 case function_packet_3_kind: //all other packets go to the repeat_queue
88a0ba7 Tons of run-time bug fixes. Should maybe work now?
Railstars authored
292 case accessory_packet_kind:
293 case reset_packet_kind:
3138243 Filled in method for ops mode programming of multi-function (loco) de…
Railstars authored
294 case ops_mode_programming_kind:
88a0ba7 Tons of run-time bug fixes. Should maybe work now?
Railstars authored
295 case other_packet_kind:
96f3ef8 initial commit
Railstars authored
296 default:
1afa334 bug fixes, fleshed out the setSpeed128 function and the repeatPacket …
Railstars authored
297 repeat_queue.insertPacket(p);
96f3ef8 initial commit
Railstars authored
298 }
299 }
1afa334 bug fixes, fleshed out the setSpeed128 function and the repeatPacket …
Railstars authored
300
301 //for enqueueing packets
8838ba6 Fixed an off-by-one bug in DCCPacketQueue that caused a memory out of…
Railstars authored
302
303 //setSpeed* functions:
304 //new_speed contains the speed and direction.
305 // a value of 0 = estop
306 // a value of 1/-1 = stop
307 // a value >1 (or <-1) means go.
308 // valid non-estop speeds are in the range [1,127] / [-127,-1] with 1 = stop
538dbdb Bugfixes to get it to compile.
Railstars authored
309 bool DCCPacketScheduler::setSpeed(unsigned int address, char new_speed, byte steps)
96f3ef8 initial commit
Railstars authored
310 {
f750bab filled in DCCPacketScheduler::setSpeed
Railstars authored
311 byte num_steps = steps;
312 //steps = 0 means use the default; otherwise use the number of steps specified
313 if(!steps)
314 num_steps = default_speed_steps;
5af0395 @DEGoodmanWilson Minor change in code for clarity.
DEGoodmanWilson authored
315
f750bab filled in DCCPacketScheduler::setSpeed
Railstars authored
316 switch(num_steps)
317 {
318 case 14:
319 return(setSpeed14(address, new_speed));
320 case 28:
321 return(setSpeed28(address, new_speed));
322 case 128:
323 return(setSpeed128(address, new_speed));
324 }
325 return false; //invalid number of steps specified.
96f3ef8 initial commit
Railstars authored
326 }
f750bab filled in DCCPacketScheduler::setSpeed
Railstars authored
327
d0e9471 Refactored the set function methods; getting ready for refactoring th…
Railstars authored
328 bool DCCPacketScheduler::setSpeed14(unsigned int address, char new_speed, bool F0)
96f3ef8 initial commit
Railstars authored
329 {
b271c1c filled in setSpeed14 and setSpeed28, probably broken.
Railstars authored
330 DCCPacket p(address);
331 byte dir = 1;
332 byte speed_data_bytes[] = {0x40};
333 unsigned int speed = new_speed;
334 if(new_speed<0)
335 {
336 dir = 0;
337 speed = new_speed * -1;
338 }
8838ba6 Fixed an off-by-one bug in DCCPacketQueue that caused a memory out of…
Railstars authored
339 if(!new_speed) //estop!
340 speed_data_bytes[0] |= 0x01; //estop
341 else if(new_speed == 1) //regular stop!
342 speed_data_bytes[0] |= 0x00; //stop
343 else //movement
344 speed_data_bytes[0] |= map(speed, 2, 127, 2, 15); //convert from [2-127] to [1-14]
b271c1c filled in setSpeed14 and setSpeed28, probably broken.
Railstars authored
345 speed_data_bytes[0] |= (0x20*dir); //flip bit 3 to indicate direction;
140a63d More runtime bug fixes. Example sketch should work properly now.
Railstars authored
346 //Serial.println(speed_data_bytes[0],BIN);
b271c1c filled in setSpeed14 and setSpeed28, probably broken.
Railstars authored
347 p.addData(speed_data_bytes,1);
243fb8b added layout initialisation as per RP 9.2.4, plus bug fixes
Railstars authored
348
349 p.setRepeat(SPEED_REPEAT);
b271c1c filled in setSpeed14 and setSpeed28, probably broken.
Railstars authored
350
243fb8b added layout initialisation as per RP 9.2.4, plus bug fixes
Railstars authored
351 p.setKind(speed_packet_kind);
352
b271c1c filled in setSpeed14 and setSpeed28, probably broken.
Railstars authored
353 //speed packets get refreshed indefinitely, and so the repeat doesn't need to be set.
354 //speed packets go to the high proirity queue
355 return(high_priority_queue.insertPacket(&p));
96f3ef8 initial commit
Railstars authored
356 }
b271c1c filled in setSpeed14 and setSpeed28, probably broken.
Railstars authored
357
1afa334 bug fixes, fleshed out the setSpeed128 function and the repeatPacket …
Railstars authored
358 bool DCCPacketScheduler::setSpeed28(unsigned int address, char new_speed)
96f3ef8 initial commit
Railstars authored
359 {
b271c1c filled in setSpeed14 and setSpeed28, probably broken.
Railstars authored
360 DCCPacket p(address);
361 byte dir = 1;
362 byte speed_data_bytes[] = {0x40};
363 unsigned int speed = new_speed;
364 if(new_speed<0)
365 {
366 dir = 0;
367 speed = new_speed * -1;
368 }
5af0395 @DEGoodmanWilson Minor change in code for clarity.
DEGoodmanWilson authored
369 // Serial.println(speed);
370 // Serial.println(dir);
371 if(speed == 0) //estop!
8838ba6 Fixed an off-by-one bug in DCCPacketQueue that caused a memory out of…
Railstars authored
372 speed_data_bytes[0] |= 0x01; //estop
373 else if(new_speed == 1) //regular stop!
374 speed_data_bytes[0] |= 0x00; //stop
375 else //movement
b271c1c filled in setSpeed14 and setSpeed28, probably broken.
Railstars authored
376 {
8838ba6 Fixed an off-by-one bug in DCCPacketQueue that caused a memory out of…
Railstars authored
377 speed_data_bytes[0] |= map(speed, 2, 127, 2, 0X1F); //convert from [2-127] to [2-31]
b271c1c filled in setSpeed14 and setSpeed28, probably broken.
Railstars authored
378 //most least significant bit has to be shufled around
379 speed_data_bytes[0] = (speed_data_bytes[0]&0xE0) | ((speed_data_bytes[0]&0x1F) >> 1) | ((speed_data_bytes[0]&0x01) << 4);
380 }
381 speed_data_bytes[0] |= (0x20*dir); //flip bit 3 to indicate direction;
5af0395 @DEGoodmanWilson Minor change in code for clarity.
DEGoodmanWilson authored
382 // Serial.println(speed_data_bytes[0],BIN);
383 // Serial.println("=======");
b271c1c filled in setSpeed14 and setSpeed28, probably broken.
Railstars authored
384 p.addData(speed_data_bytes,1);
385
243fb8b added layout initialisation as per RP 9.2.4, plus bug fixes
Railstars authored
386 p.setRepeat(SPEED_REPEAT);
387
388 p.setKind(speed_packet_kind);
389
b271c1c filled in setSpeed14 and setSpeed28, probably broken.
Railstars authored
390 //speed packets get refreshed indefinitely, and so the repeat doesn't need to be set.
391 //speed packets go to the high proirity queue
88a0ba7 Tons of run-time bug fixes. Should maybe work now?
Railstars authored
392 //return(high_priority_queue.insertPacket(&p));
b271c1c filled in setSpeed14 and setSpeed28, probably broken.
Railstars authored
393 return(high_priority_queue.insertPacket(&p));
96f3ef8 initial commit
Railstars authored
394 }
b271c1c filled in setSpeed14 and setSpeed28, probably broken.
Railstars authored
395
1afa334 bug fixes, fleshed out the setSpeed128 function and the repeatPacket …
Railstars authored
396 bool DCCPacketScheduler::setSpeed128(unsigned int address, char new_speed)
397 {
705bef6 Fixed a major bug were packets were being terribly corrupted! Idle pa…
Railstars authored
398 //why do we get things like this?
399 // 03 3F 16 15 3F (speed packet addressed to loco 03)
400 // 03 3F 11 82 AF (speed packet addressed to loco 03, speed hex 0x11);
1afa334 bug fixes, fleshed out the setSpeed128 function and the repeatPacket …
Railstars authored
401 DCCPacket p(address);
402 byte dir = 1;
8838ba6 Fixed an off-by-one bug in DCCPacketQueue that caused a memory out of…
Railstars authored
403 unsigned int speed = new_speed;
404 byte speed_data_bytes[] = {0x3F,0x00};
1afa334 bug fixes, fleshed out the setSpeed128 function and the repeatPacket …
Railstars authored
405 if(new_speed<0)
406 {
407 dir = 0;
8838ba6 Fixed an off-by-one bug in DCCPacketQueue that caused a memory out of…
Railstars authored
408 speed = new_speed * -1;
1afa334 bug fixes, fleshed out the setSpeed128 function and the repeatPacket …
Railstars authored
409 }
8838ba6 Fixed an off-by-one bug in DCCPacketQueue that caused a memory out of…
Railstars authored
410 if(!new_speed) //estop!
411 speed_data_bytes[1] = 0x01; //estop
412 else if(new_speed == 1) //regular stop!
413 speed_data_bytes[1] = 0x00; //stop
414 else //movement
415 speed_data_bytes[1] = speed; //no conversion necessary.
416
de74490 Fixed an issue where, basically, setting functions 0-8 using one of t…
Railstars authored
417 speed_data_bytes[1] |= (0x80*dir); //flip bit 7 to indicate direction;
1afa334 bug fixes, fleshed out the setSpeed128 function and the repeatPacket …
Railstars authored
418 p.addData(speed_data_bytes,2);
140a63d More runtime bug fixes. Example sketch should work properly now.
Railstars authored
419 //Serial.print(speed_data_bytes[0],BIN);
420 //Serial.print(" ");
421 //Serial.println(speed_data_bytes[1],BIN);
1afa334 bug fixes, fleshed out the setSpeed128 function and the repeatPacket …
Railstars authored
422
243fb8b added layout initialisation as per RP 9.2.4, plus bug fixes
Railstars authored
423 p.setRepeat(SPEED_REPEAT);
424
425 p.setKind(speed_packet_kind);
426
1afa334 bug fixes, fleshed out the setSpeed128 function and the repeatPacket …
Railstars authored
427 //speed packets get refreshed indefinitely, and so the repeat doesn't need to be set.
428 //speed packets go to the high proirity queue
429 return(high_priority_queue.insertPacket(&p));
430 }
d0e9471 Refactored the set function methods; getting ready for refactoring th…
Railstars authored
431
de74490 Fixed an issue where, basically, setting functions 0-8 using one of t…
Railstars authored
432 bool DCCPacketScheduler::setFunctions(unsigned int address, uint16_t functions)
433 {
8838ba6 Fixed an off-by-one bug in DCCPacketQueue that caused a memory out of…
Railstars authored
434 // Serial.println(functions,HEX);
de74490 Fixed an issue where, basically, setting functions 0-8 using one of t…
Railstars authored
435 if(setFunctions0to4(address, functions&0x1F))
436 if(setFunctions5to8(address, (functions>>5)&0x0F))
437 if(setFunctions9to12(address, (functions>>9)&0x0F))
438 return true;
439 return false;
440 }
441
d0e9471 Refactored the set function methods; getting ready for refactoring th…
Railstars authored
442 bool DCCPacketScheduler::setFunctions(unsigned int address, byte F0to4, byte F5to8, byte F9to12)
443 {
444 if(setFunctions0to4(address, F0to4))
445 if(setFunctions5to8(address, F5to8))
446 if(setFunctions9to12(address, F9to12))
447 return true;
448 return false;
449 }
450
451 bool DCCPacketScheduler::setFunctions0to4(unsigned int address, byte functions)
96f3ef8 initial commit
Railstars authored
452 {
8838ba6 Fixed an off-by-one bug in DCCPacketQueue that caused a memory out of…
Railstars authored
453 // Serial.println("setFunctions0to4");
454 // Serial.println(functions,HEX);
6e67e35 Added methods to activate functions; updated example sketch to toggle…
Railstars authored
455 DCCPacket p(address);
456 byte data[] = {0x80};
457
de74490 Fixed an issue where, basically, setting functions 0-8 using one of t…
Railstars authored
458 //Obnoxiously, the headlights (F0, AKA FL) are not controlled
459 //by bit 0, but by bit 4. Really?
6e67e35 Added methods to activate functions; updated example sketch to toggle…
Railstars authored
460
de74490 Fixed an issue where, basically, setting functions 0-8 using one of t…
Railstars authored
461 //get functions 1,2,3,4
462 data[0] |= (functions>>1) & 0x0F;
463 //get functions 0
464 data[0] |= (functions&0x01) << 4;
465
6e67e35 Added methods to activate functions; updated example sketch to toggle…
Railstars authored
466 p.addData(data,1);
de74490 Fixed an issue where, basically, setting functions 0-8 using one of t…
Railstars authored
467 p.setKind(function_packet_1_kind);
6e67e35 Added methods to activate functions; updated example sketch to toggle…
Railstars authored
468 p.setRepeat(FUNCTION_REPEAT);
469 return(low_priority_queue.insertPacket(&p));
96f3ef8 initial commit
Railstars authored
470 }
6e67e35 Added methods to activate functions; updated example sketch to toggle…
Railstars authored
471
472
d0e9471 Refactored the set function methods; getting ready for refactoring th…
Railstars authored
473 bool DCCPacketScheduler::setFunctions5to8(unsigned int address, byte functions)
96f3ef8 initial commit
Railstars authored
474 {
8838ba6 Fixed an off-by-one bug in DCCPacketQueue that caused a memory out of…
Railstars authored
475 // Serial.println("setFunctions5to8");
476 // Serial.println(functions,HEX);
6e67e35 Added methods to activate functions; updated example sketch to toggle…
Railstars authored
477 DCCPacket p(address);
de74490 Fixed an issue where, basically, setting functions 0-8 using one of t…
Railstars authored
478 byte data[] = {0xB0};
6e67e35 Added methods to activate functions; updated example sketch to toggle…
Railstars authored
479
480 data[0] |= functions & 0x0F;
481
482 p.addData(data,1);
de74490 Fixed an issue where, basically, setting functions 0-8 using one of t…
Railstars authored
483 p.setKind(function_packet_2_kind);
6e67e35 Added methods to activate functions; updated example sketch to toggle…
Railstars authored
484 p.setRepeat(FUNCTION_REPEAT);
d0e9471 Refactored the set function methods; getting ready for refactoring th…
Railstars authored
485 return(low_priority_queue.insertPacket(&p));
486 }
6e67e35 Added methods to activate functions; updated example sketch to toggle…
Railstars authored
487
d0e9471 Refactored the set function methods; getting ready for refactoring th…
Railstars authored
488 bool DCCPacketScheduler::setFunctions9to12(unsigned int address, byte functions)
489 {
8838ba6 Fixed an off-by-one bug in DCCPacketQueue that caused a memory out of…
Railstars authored
490 // Serial.println("setFunctions9to12");
491 // Serial.println(functions,HEX);
d0e9471 Refactored the set function methods; getting ready for refactoring th…
Railstars authored
492 DCCPacket p(address);
de74490 Fixed an issue where, basically, setting functions 0-8 using one of t…
Railstars authored
493 byte data[] = {0xA0};
d0e9471 Refactored the set function methods; getting ready for refactoring th…
Railstars authored
494
495 //least significant four functions (F5--F8)
de74490 Fixed an issue where, basically, setting functions 0-8 using one of t…
Railstars authored
496 data[0] |= functions & 0x0F;
d0e9471 Refactored the set function methods; getting ready for refactoring th…
Railstars authored
497
498 p.addData(data,1);
de74490 Fixed an issue where, basically, setting functions 0-8 using one of t…
Railstars authored
499 p.setKind(function_packet_3_kind);
d0e9471 Refactored the set function methods; getting ready for refactoring th…
Railstars authored
500 p.setRepeat(FUNCTION_REPEAT);
6e67e35 Added methods to activate functions; updated example sketch to toggle…
Railstars authored
501 return(low_priority_queue.insertPacket(&p));
96f3ef8 initial commit
Railstars authored
502 }
6e67e35 Added methods to activate functions; updated example sketch to toggle…
Railstars authored
503
d0e9471 Refactored the set function methods; getting ready for refactoring th…
Railstars authored
504
96f3ef8 initial commit
Railstars authored
505 //other cool functions to follow. Just get these working first, I think.
506
507 //bool DCCPacketScheduler::setTurnout(unsigned int address)
508 //bool DCCPacketScheduler::unsetTurnout(unsigned int address)
425df81 only beginning with ops mode programming methods
Railstars authored
509
3138243 Filled in method for ops mode programming of multi-function (loco) de…
Railstars authored
510 bool DCCPacketScheduler::opsProgramCV(unsigned int address, unsigned int CV, byte CV_data)
425df81 only beginning with ops mode programming methods
Railstars authored
511 {
3138243 Filled in method for ops mode programming of multi-function (loco) de…
Railstars authored
512 //format of packet:
513 // {preamble} 0 [ AAAAAAAA ] 0 111011VV 0 VVVVVVVV 0 DDDDDDDD 0 EEEEEEEE 1 (write)
514 // {preamble} 0 [ AAAAAAAA ] 0 111001VV 0 VVVVVVVV 0 DDDDDDDD 0 EEEEEEEE 1 (verify)
515 // {preamble} 0 [ AAAAAAAA ] 0 111010VV 0 VVVVVVVV 0 DDDDDDDD 0 EEEEEEEE 1 (bit manipulation)
516 // only concerned with "write" form here.
517
518 DCCPacket p(address);
519 byte data[] = {0xEC, 0x00, 0x00};
425df81 only beginning with ops mode programming methods
Railstars authored
520
3138243 Filled in method for ops mode programming of multi-function (loco) de…
Railstars authored
521 // split the CV address up among data bytes 0 and 1
522 data[0] |= ((CV-1) & 0x3FF) >> 8;
523 data[1] = (CV-1) & 0xFF;
524 data[2] = CV_data;
525
526 p.addData(data,3);
527 p.setKind(ops_mode_programming_kind);
528 p.setRepeat(OPS_MODE_PROGRAMMING_REPEAT);
529
530 return(low_priority_queue.insertPacket(&p));
425df81 only beginning with ops mode programming methods
Railstars authored
531 }
96f3ef8 initial commit
Railstars authored
532
533 //more specific functions
534
65f0050 Enable e-stop routines. Oops!
Railstars authored
535 //broadcast e-stop command
96f3ef8 initial commit
Railstars authored
536 bool DCCPacketScheduler::eStop(void)
537 {
65f0050 Enable e-stop routines. Oops!
Railstars authored
538 // 111111111111 0 00000000 0 01DC0001 0 EEEEEEEE 1
539 DCCPacket e_stop_packet = DCCPacket(); //address 0
d752e9e Fixed typos in both versions of DCCPacketScheduler::eStop. Thanks to …
Railstars authored
540 byte data[] = {0x71}; //01110001
243fb8b added layout initialisation as per RP 9.2.4, plus bug fixes
Railstars authored
541 e_stop_packet.addData(data,1);
96f3ef8 initial commit
Railstars authored
542 e_stop_packet.setKind(e_stop_packet_kind);
d752e9e Fixed typos in both versions of DCCPacketScheduler::eStop. Thanks to …
Railstars authored
543 e_stop_packet.setRepeat(10);
65f0050 Enable e-stop routines. Oops!
Railstars authored
544 e_stop_queue.insertPacket(&e_stop_packet);
96f3ef8 initial commit
Railstars authored
545 }
546
547 bool DCCPacketScheduler::eStop(unsigned int address)
548 {
65f0050 Enable e-stop routines. Oops!
Railstars authored
549 // 111111111111 0 0AAAAAAA 0 01001001 0 EEEEEEEE 1
550 // or
551 // 111111111111 0 0AAAAAAA 0 01000001 0 EEEEEEEE 1
96f3ef8 initial commit
Railstars authored
552 DCCPacket e_stop_packet = DCCPacket(address);
d752e9e Fixed typos in both versions of DCCPacketScheduler::eStop. Thanks to …
Railstars authored
553 byte data[] = {0x41}; //01000001
65f0050 Enable e-stop routines. Oops!
Railstars authored
554 e_stop_packet.addData(data,1);
96f3ef8 initial commit
Railstars authored
555 e_stop_packet.setKind(e_stop_packet_kind);
d752e9e Fixed typos in both versions of DCCPacketScheduler::eStop. Thanks to …
Railstars authored
556 e_stop_packet.setRepeat(10);
65f0050 Enable e-stop routines. Oops!
Railstars authored
557 e_stop_queue.insertPacket(&e_stop_packet);
96f3ef8 initial commit
Railstars authored
558 }
559
560 //to be called periodically within loop()
561 void DCCPacketScheduler::update(void) //checks queues, puts whatever's pending on the rails via global current_packet. easy-peasy
562 {
705bef6 Fixed a major bug were packets were being terribly corrupted! Idle pa…
Railstars authored
563 DCC_waveform_generation_hasshin();
564
96f3ef8 initial commit
Railstars authored
565 //TODO ADD POM QUEUE?
566 if(!current_byte_counter) //if the ISR needs a packet:
567 {
568 DCCPacket p = DCCPacket();
569 //Take from e_stop queue first, then high priority queue.
570 //every fifth packet will come from low priority queue.
571 //every 20th packet will come from periodic refresh queue. (Why 20? because. TODO reasoning)
572 //if there's a packet ready, and the counter is not divisible by 5
573 //first, we need to know which queues have packets ready, and the state of the this->packet_counter.
574 if( !e_stop_queue.isEmpty() ) //if there's an e_stop packet, send it now!
575 {
576 //e_stop
243fb8b added layout initialisation as per RP 9.2.4, plus bug fixes
Railstars authored
577 e_stop_queue.readPacket(&p); //nothing more to do. e_stop_queue is a repeat_queue, so automatically repeats where necessary.
96f3ef8 initial commit
Railstars authored
578 }
579 else
580 {
88a0ba7 Tons of run-time bug fixes. Should maybe work now?
Railstars authored
581 bool doHigh = high_priority_queue.notEmpty() && high_priority_queue.notRepeat(last_packet_address);
140a63d More runtime bug fixes. Example sketch should work properly now.
Railstars authored
582 bool doLow = low_priority_queue.notEmpty() && low_priority_queue.notRepeat(last_packet_address) &&
583 !((packet_counter % LOW_PRIORITY_INTERVAL) && doHigh);
584 bool doRepeat = repeat_queue.notEmpty() && repeat_queue.notRepeat(last_packet_address) &&
585 !((packet_counter % REPEAT_INTERVAL) && (doHigh || doLow));
6c5699b Shaved down on some of the classes to reduce memory footprint; Total …
Railstars authored
586 //bool doRefresh = periodic_refresh_queue.notEmpty() && periodic_refresh_queue.notRepeat(last_packet_address) &&
587 // !((packet_counter % PERIODIC_REFRESH_INTERVAL) && (doHigh || doLow || doRepeat));
96f3ef8 initial commit
Railstars authored
588 //examine queues in order from lowest priority to highest.
6c5699b Shaved down on some of the classes to reduce memory footprint; Total …
Railstars authored
589 //if(doRefresh)
590 //{
591 // periodic_refresh_queue.readPacket(&p);
592 // ++packet_counter;
593 //}
594 //else if(doRepeat)
595 if(doRepeat)
96f3ef8 initial commit
Railstars authored
596 {
597 repeat_queue.readPacket(&p);
88a0ba7 Tons of run-time bug fixes. Should maybe work now?
Railstars authored
598 ++packet_counter;
96f3ef8 initial commit
Railstars authored
599 }
600 else if(doLow)
601 {
602 low_priority_queue.readPacket(&p);
88a0ba7 Tons of run-time bug fixes. Should maybe work now?
Railstars authored
603 ++packet_counter;
96f3ef8 initial commit
Railstars authored
604 }
605 else if(doHigh)
606 {
607 high_priority_queue.readPacket(&p);
88a0ba7 Tons of run-time bug fixes. Should maybe work now?
Railstars authored
608 ++packet_counter;
96f3ef8 initial commit
Railstars authored
609 }
88a0ba7 Tons of run-time bug fixes. Should maybe work now?
Railstars authored
610 //if none of these conditions hold, DCCPackets initialize to the idle packet, so that's what'll get sent.
611 //++packet_counter; //it's a byte; let it overflow, that's OK.
612 //enqueue the packet for repitition, if necessary:
613 repeatPacket(&p);
96f3ef8 initial commit
Railstars authored
614 }
81ca2d3 more bugfixes
Railstars authored
615 last_packet_address = p.getAddress(); //remember the address to compare with the next packet
616 current_packet_size = p.getBitstream(current_packet); //feed to the starving ISR.
140a63d More runtime bug fixes. Example sketch should work properly now.
Railstars authored
617 //output the packet, for checking:
618 //for(byte i = 0; i < current_packet_size; ++i)
619 //{
620 // Serial.print(current_packet[i],BIN);
621 // Serial.print(" ");
622 //}
623 //Serial.println("");
88a0ba7 Tons of run-time bug fixes. Should maybe work now?
Railstars authored
624 current_byte_counter = current_packet_size;
96f3ef8 initial commit
Railstars authored
625 }
6274268 Added tentative support for Arduino MEGA
Railstars authored
626 }
Something went wrong with that request. Please try again.