nano_seindecoder_inc_DCC_simple.ino 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. ///////////////////////////////////////////////////////
  2. //
  3. // DCC packet analyze: Ruud Boer, October 2015
  4. // DCC packet capture: Robin McKay, March 2014
  5. //
  6. // The DCC signal is detected on Arduino digital pin 2
  7. //
  8. // Set theSerial Monitor Baud Rate to 38400 !!
  9. //
  10. // Keyboard commands that can be sent viaSerial Monitor:
  11. // 1 = 1s refresh time
  12. // 2 = 2s
  13. // 3 = 4s (default)
  14. // 4 = 8s
  15. // 5 = 16s
  16. // 6 = 4 DCC packet buffer
  17. // 7 = 8
  18. // 8 = 16
  19. // 9 = 32 (default)
  20. // 0 = 64
  21. // a = show accessory packets toggle
  22. // l = show locomotive packets toggle
  23. //
  24. ////////////////////////////////////////////////////////
  25. byte refreshTime = 4; // Time between DCC packets buffer refreshes in s
  26. byte packetBufferSize = 2; // DCC packets buffer size
  27. #define TIMER_PRESCALER 64
  28. #define DccBitTimerCount (F_CPU * 80L / TIMER_PRESCALER / 1000000L)
  29. // 16000000 * 80 / 64 / 1000000 = 20; 20 x 4usecs = 80us
  30. boolean packetEnd;
  31. boolean preambleFound;
  32. const byte bitBufSize = 50; // number of slots for bits
  33. volatile byte bitBuffer[bitBufSize];
  34. volatile byte bitBuffHead = 1;
  35. volatile byte bitBuffTail = 0;
  36. byte pktByteCount = 0;
  37. byte packetBytesCount;
  38. byte preambleOneCount;
  39. byte dccPacket[6]; // buffer to hold a packet
  40. byte instrByte1;
  41. byte decoderType; //0=Loc, 1=Acc
  42. byte bufferCounter = 0;
  43. byte isDifferentPacket = 0;
  44. byte showLoc = 1;
  45. byte showAcc = 1;
  46. unsigned int decoderAddress;
  47. unsigned int packetBuffer[64];
  48. unsigned int packetNew = 0;
  49. unsigned long timeToRefresh = millis() + refreshTime * 1000;
  50. //========================
  51. //custom vars
  52. #include<SPI.h>
  53. const int boards = 3 ;
  54. const int registers = boards*3;
  55. const int outputCount = registers*8;
  56. const int signalValsLength = outputCount; //2signalvals = 1 sein
  57. int signalVals[signalValsLength];
  58. byte data[registers]; //data array die naar de registers wordt gestuurd, index register , value = byte (00000000)
  59. int bitCounter = 0; //bits in byte 0 tot 7
  60. int byteCounter = 0; //byte gelijk aan register
  61. int val = 0; //tijdelijk var om de value voor de bit te bepalen
  62. bool testMode = true;
  63. int testOffset = 0;
  64. int testInterval = 1000;
  65. unsigned long updateTestAt = millis()+testInterval;
  66. //end custom vars
  67. //custom functions
  68. void setTestValues(bool val){
  69. if(val == testMode)
  70. return;
  71. testMode = val;
  72. Serial.print("setting testVal ");
  73. Serial.println(val);
  74. if(!val){
  75. processData();
  76. updateRegisters();
  77. }else{
  78. updateTestData();
  79. updateRegisters();
  80. }
  81. }
  82. void updateTestData(){
  83. bitCounter = 0;
  84. byteCounter = 0;
  85. if(testOffset == 3)
  86. testOffset = 0;
  87. for (int i = 0; i < signalValsLength; i++){
  88. if(bitCounter > 7){
  89. byteCounter++;
  90. bitCounter = 0;
  91. }
  92. //stap door
  93. if((i+testOffset) % 3 != 0)
  94. bitSet(data[byteCounter],7-bitCounter);
  95. else
  96. bitClear(data[byteCounter],7-bitCounter);
  97. bitCounter++;
  98. //random*/
  99. /*
  100. if(random(0,2) == 1)
  101. bitSet(data[byteCounter],7-bitCounter);
  102. else
  103. bitClear(data[byteCounter],7-bitCounter);
  104. bitCounter++;
  105. //*/
  106. }
  107. testOffset++;
  108. }
  109. void processData(){
  110. Serial.println("1");
  111. bitCounter = 0;
  112. byteCounter = 0;
  113. for (int i = 0; i < signalValsLength; i++){
  114. if(bitCounter > 7){
  115. byteCounter++;
  116. bitCounter = 0;
  117. }
  118. if(signalVals[i] == 1)
  119. bitSet(data[byteCounter],7-bitCounter);
  120. else
  121. bitClear(data[byteCounter],7-bitCounter);
  122. bitCounter++;
  123. }
  124. }
  125. void printStatus(int value){
  126. switch(value){
  127. case 0:
  128. Serial.print("groen");
  129. break;
  130. case 1:
  131. Serial.print("rood");
  132. break;
  133. case 3:
  134. Serial.print("oranje");
  135. break;
  136. default:
  137. Serial.print("invalid signal");
  138. break;
  139. }
  140. Serial.print(" ");
  141. Serial.println(value);
  142. }
  143. void setupSpi(){
  144. SPI.begin();
  145. pinMode(SS, OUTPUT);
  146. digitalWrite(SS, HIGH);
  147. SPI.setDataMode(3);
  148. SPI.setClockDivider(4);
  149. SPI.setBitOrder(LSBFIRST);
  150. }
  151. void updateRegisters(){
  152. //Serial.println("2");
  153. digitalWrite(SS, LOW);
  154. //digitalWrite(13, LOW);
  155. for(int r = registers-1; r >= 0 ; r--){
  156. SPI.transfer(data[r]); // high byte
  157. }
  158. digitalWrite(SS, HIGH);
  159. digitalWrite(13, HIGH);
  160. }
  161. void resetData(){
  162. return;
  163. bitCounter = 0;
  164. byteCounter = 0;
  165. for(int r = registers-1; r >= 0 ; r--){
  166. data[r] = 0; // reset Byte
  167. }
  168. }
  169. void handleData(int addr , bool val){
  170. if(addr == 799){
  171. setTestValues(val);
  172. }
  173. if(addr <= 899)
  174. return;
  175. addr = addr-900;
  176. if(val)
  177. signalVals[addr] = 0;
  178. else
  179. signalVals[addr] = 1;
  180. processData();
  181. updateRegisters();
  182. }
  183. //end custom functions
  184. void getPacket() {
  185. preambleFound = false;
  186. packetEnd = false;
  187. packetBytesCount = 0;
  188. preambleOneCount = 0;
  189. while (! packetEnd) {
  190. if (preambleFound) getNextByte();
  191. else checkForPreamble();
  192. }
  193. }
  194. //========================
  195. void checkForPreamble() {
  196. byte nextBit = getBit();
  197. if (nextBit == 1) preambleOneCount++;
  198. if (preambleOneCount < 10 && nextBit == 0) preambleOneCount = 0;
  199. if (preambleOneCount >= 10 && nextBit == 0) preambleFound = true;
  200. }
  201. //========================
  202. void getNextByte() {
  203. byte newByte = 0;
  204. for (byte n = 0; n < 8; n++) newByte = (newByte << 1) + getBit();
  205. packetBytesCount ++;
  206. dccPacket[packetBytesCount] = newByte;
  207. dccPacket[0] = packetBytesCount;
  208. if (getBit() == 1) packetEnd = true;
  209. }
  210. //========================
  211. byte getBit() {
  212. // gets the next bit from the bitBuffer
  213. // if the buffer is empty it will wait indefinitely for bits to arrive
  214. byte nbs = bitBuffHead;
  215. while (nbs == bitBuffHead) byte nbs = nextBitSlot(bitBuffTail); //Buffer empty
  216. bitBuffTail = nbs;
  217. return (bitBuffer[bitBuffTail]);
  218. }
  219. //========================
  220. void beginBitDetection() {
  221. TCCR0A &= B11111100;
  222. attachInterrupt(0, startTimer, RISING);
  223. }
  224. //========================
  225. void startTimer() {
  226. OCR0B = TCNT0 + DccBitTimerCount;
  227. TIMSK0 |= B00000100;
  228. TIFR0 |= B00000100;
  229. }
  230. //========================
  231. ISR(TIMER0_COMPB_vect) {
  232. byte bitFound = ! ((PIND & B00000100) >> 2);
  233. TIMSK0 &= B11111011;
  234. byte nbs = nextBitSlot(bitBuffHead);
  235. if (nbs == bitBuffTail) return;
  236. else {
  237. bitBuffHead = nbs;
  238. bitBuffer[bitBuffHead] = bitFound;
  239. }
  240. }
  241. //========================
  242. byte nextBitSlot(byte slot) {
  243. slot ++;
  244. if (slot >= bitBufSize) slot = 0;
  245. return (slot);
  246. }
  247. //========================
  248. void printPacket() {
  249. Serial.print(" ");
  250. for (byte n = 1; n < pktByteCount; n++) {
  251. Serial.print(" ");
  252. Serial.print(dccPacket[n], BIN);
  253. }
  254. Serial.println(" ");
  255. }
  256. //========================
  257. void refreshBuffer() {
  258. timeToRefresh = millis() + refreshTime * 500;
  259. for (byte n = 0; n < packetBufferSize; n++) packetBuffer[n] = 0;
  260. bufferCounter = 0;
  261. Serial.println("-");
  262. /*
  263. Serial.print("Loc ");
  264. Serial.print(showLoc);
  265. Serial.print(" / Acc ");
  266. Serial.print(showAcc);
  267. Serial.print(" / Time ");
  268. Serial.print(refreshTime);
  269. Serial.print(" / Buff ");
  270. Serial.println(packetBufferSize);
  271. Serial.println(" ");
  272. */
  273. }
  274. //========================
  275. void setup() {
  276. Serial.begin(38400); // 38400 when on DCC, 9600 when testing on 123Circuits !!!!!!!!!!!!!!!!!!!!!!!
  277. Serial.println("---");
  278. Serial.println("DCC Packet Analyze started");
  279. Serial.print("Updates every ");
  280. Serial.print(refreshTime);
  281. Serial.println(" seconds");
  282. Serial.println("---");
  283. setupSpi();
  284. processData();
  285. updateRegisters();
  286. beginBitDetection(); //Uncomment this line when on DCC !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  287. }
  288. //====================
  289. void loop() {
  290. updateRegisters();
  291. getPacket(); //Uncomment this line when on DCC !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  292. byte speed;
  293. byte checksum = 0;
  294. if (millis() > timeToRefresh){
  295. refreshBuffer();
  296. //processData();
  297. //updateRegisters();
  298. }
  299. if(millis() > updateTestAt && testMode )
  300. {
  301. Serial.println("running test");
  302. updateTestAt = millis()+testInterval;
  303. updateTestData();
  304. updateRegisters();
  305. }
  306. pktByteCount = dccPacket[0];
  307. if (!pktByteCount){
  308. Serial.println("nodata");
  309. return; // No new packet available
  310. }
  311. for (byte n = 1; n <= pktByteCount; n++) checksum ^= dccPacket[n];
  312. //checksum=0; //Comment this line when on DCC !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  313. if (checksum) {
  314. Serial.println("invalid checkSum");
  315. return; // Invalid Checksum
  316. }
  317. else { // There is a new packet with a correct checksum
  318. isDifferentPacket = 1;
  319. for (byte n = 0; n < packetBufferSize ; n++) { // Check if packet is not already in the buffer.
  320. // The checksum byte is used for the test, not ideal, some new packets may not show (only 256 different checksums)
  321. if (dccPacket[pktByteCount] == packetBuffer[n]) isDifferentPacket = 0;
  322. }
  323. if (isDifferentPacket) { // packet does not yet exist in the packet buffer
  324. packetBuffer[bufferCounter] = dccPacket[pktByteCount]; // add new packet to the buffer
  325. bufferCounter = (++bufferCounter) & (packetBufferSize - 1);
  326. if (dccPacket[1] == B11111111) { //Idle packet
  327. Serial.println("Idle ");
  328. return;
  329. }
  330. if (!bitRead(dccPacket[1], 7)) { //bit7=0 -> Loc Decoder Short Address
  331. decoderAddress = dccPacket[1];
  332. instrByte1 = dccPacket[2];
  333. decoderType = 0;
  334. }
  335. else {
  336. if (bitRead(dccPacket[1], 6)) { //bit7=1 AND bit6=1 -> Loc Decoder Long Address
  337. decoderAddress = 256 * (dccPacket[1] & B00000111) + dccPacket[2];
  338. instrByte1 = dccPacket[3];
  339. decoderType = 0;
  340. }
  341. else { //bit7=1 AND bit6=0 -> Accessory Decoder
  342. decoderAddress = dccPacket[1] & B00111111;
  343. instrByte1 = dccPacket[2];
  344. decoderType = 1;
  345. }
  346. }
  347. if (decoderType) { // Accessory Basic
  348. if (showAcc) {
  349. if (instrByte1 & B10000000) { // Basic Accessory
  350. decoderAddress = (((~instrByte1)&B01110000) << 2) + decoderAddress;
  351. byte port = (instrByte1 & B00000110) >> 1;
  352. int decAddr = (decoderAddress) * 4 + port + 1;
  353. Serial.print("Acc ");
  354. Serial.print(decAddr);
  355. Serial.print(" ");
  356. Serial.print(decoderAddress);
  357. Serial.print(":");
  358. Serial.print(port);
  359. Serial.print(" ");
  360. Serial.print(bitRead(instrByte1, 3));
  361. if (bitRead(instrByte1, 0)){
  362. Serial.print(" On");
  363. }else
  364. {
  365. Serial.print(" Off");
  366. }
  367. //custom code
  368. handleData(decAddr ,bitRead(instrByte1, 0));
  369. //end custom code
  370. }
  371. else { // Accessory Extended NMRA spec is not clear about address and instruction format !!!
  372. Serial.print("Acc Ext ");
  373. decoderAddress = (decoderAddress << 5) + ((instrByte1 & B01110000) >> 2) + ((instrByte1 & B00000110) >> 1);
  374. Serial.print(decoderAddress);
  375. Serial.print(" Asp ");
  376. Serial.print(dccPacket[3], BIN);
  377. }
  378. printPacket();
  379. }
  380. }
  381. else { // Loc / Multi Function Decoder
  382. }
  383. }
  384. }
  385. if (Serial.available()) {
  386. Serial.println(" ");
  387. switch (Serial.read()) {
  388. case 49:
  389. Serial.println("Refresh Time = 1s");
  390. refreshTime = 1;
  391. break;
  392. case 50:
  393. Serial.println("Refresh Time = 2s");
  394. refreshTime = 2;
  395. break;
  396. case 51:
  397. Serial.println("Refresh Time = 4s");
  398. refreshTime = 4;
  399. break;
  400. case 52:
  401. Serial.println("Refresh Time = 8s");
  402. refreshTime = 8;
  403. break;
  404. case 53:
  405. Serial.println("Refresh Time = 16s");
  406. refreshTime = 16;
  407. break;
  408. case 54:
  409. Serial.println("Buffer Size = 4");
  410. packetBufferSize = 2;
  411. break;
  412. case 55:
  413. Serial.println("Buffer Size = 8");
  414. packetBufferSize = 8;
  415. break;
  416. case 56:
  417. Serial.println("Buffer Size = 16");
  418. packetBufferSize = 16;
  419. break;
  420. case 57:
  421. Serial.println("Buffer Size = 32");
  422. packetBufferSize = 32;
  423. break;
  424. case 48:
  425. Serial.println("Buffer Size = 64");
  426. packetBufferSize = 64;
  427. break;
  428. case 97:
  429. if (showAcc) showAcc = 0; else showAcc = 1;
  430. Serial.print("show acc packets = ");
  431. Serial.println(showAcc);
  432. break;
  433. case 108:
  434. if (showLoc) showLoc = 0; else showLoc = 1;
  435. Serial.print("show loc packets = ");
  436. Serial.println(showLoc);
  437. break;
  438. }
  439. Serial.println(" ");
  440. }
  441. }
  442. //=====================