PROTOCOL BETWEEN HOST AND MASTER PIC ==================================== 9600 8N1 over the serial port. The PIC must obey the host's flow control line, so that if the host gets backed up none of the PICs messages can get lost. (If this is too hard, then the PIC should attempt to buffer some data while the host is busy but if the PIC's buffer gets too full it should panic.) Each message consists of a number of 8-bit bytes. The top bit of each byte is 1 iff there is another byte in the message. First Second ASCII Message Brief Byte byte etc. or hex name description From host to PIC: > 1 0100 TTT 0 TTTTTTT (a0) POINT Point T fire > 1 1111 111 .... (ff) NMRADATA NMRA data > 1 0001 XXX 0 XXXXXXX (88+) PING Ping `X' (please Pong `X(+)0x5a') > 1 0010 RRR E RRR... (90+) POLARITY Set polarity > 1 0011 000 0 MMMMMMM (98+) WATCHDOG W'dog reset, t/o ms from now > 0 0010 001 (11) ON Power on > 0 0010 000 (10) OFF Power off > 1 0101 WWW 0 WWWWWWV (a1) WAGGLE Set pin WWWWWWWWW to level V ;> 00000000 CRASHED Acknowledge panic, go to readout mode ;> 00001010 (0a) TELLMODE Confirm mode - say HELLO or CRASHED ; if crashed, undoes the effect of ack ; In crash readout mode: ; ; 00000000 MS Select crash readout mode if not already ; Reset crash readout pointer to 0 ; ; 00001000 Acknowledge RS232 framing error or overrun ; 00001001 Reboot ; ; 1vvvvvvv M Prepare byte 0vvvvvvv for transmission to the slave ; ; 00000nnn M (n>0) prepare to receive nnnn bytes from slave ; 0001nnnn M (n>0) transmit nnnn bytes of our own from the ; readout pointer ; ; 001sssss M Select slave S^0x10. Then: ; After 1vvvvvvv ; Transmit just 0vvvvvvv to slave ; and then send some some unspecified byte to host ; After 0000nnnn ; Receive nnnn bytes, forwarding each one ; to the host. ; After the transaction is complete, 1vvvvvvv ; or 0000nnnn must be specified again before ; 001sssss is repeated. ; ; 01bbbbbb MS Supply 6 bits for crash readout pointer ; (crash readout mode only) ; Effect is FSR << 6; FSR |= bbbbbb From PIC to host: < 1 001Y SSS 0 SSSSSSS (9?) DETECT Train is (Y=1) or is not (Y=0) at S < 1 0001 XXX 0 XXXXXXX (88+) PONG Pong `X' (reply to Ping `X(+)0x5a') < 1 100 0001 0 NNNNNNN (ENQ) SPURIOUS Number of spurious fault interrupts < 0 000 1001 (HT) HELLO I am booted < 0 000 1011 (VT) AAARGH Followed by debug chars (only) < 0 000 1101 (CR) WTIMEOUT Watchdog timeout happened < 0 000 0111 (BEL) FAULT Fault exists < 0 000 0110 (ACK) RETRIABLE Fault may be tested once more < 0 000 0100 (ENQ) WAGGLED Pin changed according to WAGGLE < 0 0100 PPP (20+) POINTED Point change done using capacitor P < 0 0101 PPP (28+) CHARGED Point capacitor P is now charged < 0 00000 00 NUL Junk, prob because layout turned off < 0 00000 FF NMRADONE Have processed F NMRADATA message(s) < 0000 1010 (LF) } debugging output 0x0a (newline) and < 001C CCCC } (works with terminal 0x20-0x7e < 01CC CCCC except 0111 1111 } emulator, or host logs) (printing ASCII) (These are all shown big-endian, and all of the numerical representations are big-endian too. Where a number is split across two or more bytes, the relevant bits are to be concatenated, in the order shown, ie bits from the MS byte first, into a larger number.) HELLO, AAARGH and debugging output ---------------------------------- When the master PIC starts up and has confirmed that all is well (all of the other PICs are there, etc), it should send HELLO once. If the host makes a mistake (eg, sends an unknown command, or does something else wrong) or something goes horribly wrong, the master PIC should send AAARGH. The PIC may always send printing ASCII characters and spaces and newlines (ie, bytes 0x0a, 0x20-0x7e). These will print out nicely in a terminal emulator, if that's what's running on the host. If the host is running the real software, that software will put the characters sent in its log or somewhere else nicely accessible. Apart from debugging output, the PIC should send nothing before HELLO and nothing after AAARGH. POWER AND FAULT --------------- The host can send ON and OFF to turn the track (and various other stuff) on and off. After ON, the track power should be enabled and transmitting NMRA idle, and the CDU should be enabled. If the power is ON, and a track power short circuit is detected, the PIC should send FAULT. When the short circuit is removed, the PIC should send FIXED but not fully reenable track power; track power should be reenabled when the host transmits ON. Track and CDU Track and CDU ----->-----. disabled -------ON-------> enabled \ . __ __ | /|\ |`-._ ON ,-'| |,--------<-------. | | `-._ ,-' | | | OFF| OFF `-._ ,-' |Short | | | ,-' _ FAULT| circuit | | ,->-'| ,+' `-._ | detected | | / | ,-' | `-._ V | | | ' | ` | | | Track disabled | Wait for post-fault | | | CDU enabled <-----500ms------ minimum off time | | | User Fault | RETRIABLE User fault | | | flashes slowly | flashes rapidly | | | / | | \ ' | | `----- Track disabled ---------------->-------------------' / CDU enabled ----------------<----------------------' User Fault lit WTIMEOUT watchdog timer runs out If ON or OFF are issued in the first 500ms following a short circuit, they are ignored. POINTS and CDU -------------- The ON command should cause the CDU to be enabled (and of course all point motor outputs should be disabled first - see README.circuitry). Following ON the host must wait until it receives CHARGED before attempting to change a point. After CHARGED it may send POINT, to activate the point and direction specified by T. The PICs will report POINTED when the point has stopped moving, and CHARGED when the CDU is ready to change another point (the host may not send POINT for a point on the same CDU until then). Currently there is only one CDU so P is always 0 (but the PICs need not check that the received P value is 0; they may simply assume it). ----ON-----> CDU is ------CHARGED---> CDU is charged charging _. and ready /| ,----CHARGED--' | / |POINT / | Point has ' V changed; CDU is recharging <----POINTED---- Point is changing Note that OFF will turn the CDU off, and a short circuit (FAULT) will turn it off 500ms later (this delay avoids losing races where the host sends a point change instruction just before a short happens). PING and PONG ------------- The host may send PING at any time; the PIC should reply with PONG with the same X as was in the PING message, but with the bottom byte xor'd with 0x5a.. The host may not send another PING until the first one's PONG has come back. POLARITY -------- The POLARITY command may be sent whether the track power is enabled or disabled. The polarity of each segment is `unreversed' after ON; it remains constant until from then on except as modified by POLARITY. The command is of variable length (but at least two bytes): > 1 0010 RRR E RRR... POLARITY Set polarity Each byte after the first contains 7 more R bits. The first R bit (most significant R bit in the first byte) corresponds to track reversal segment 1; The next bit (2nd most significant bit in the first byte) corresponds to track reversal segment 2; and so on. Bits which do not correspond to defined reversal segments will be ignored by the PICs. The host must send exactly as many bytes as are necessary to include all of the reversal segments for each reversers board (for every potential reversal segment, regardless of whether that segment is a defined segment corresponding to some actual track; however a board with _no_ reversers segments used does not count). For example, if there are 14 reversible segments (numbered 1 to 14) then the following message 1 0010 000 1 000 1000 0 111 1010 Actual message (E RRR) (E RRR RRRR) (E RRR R---) } helpful annotations 1 111 1111 } and commentary 123 456 7890 123 4567 } specifies to reverse segments 7 and 11 to 14. The trailing bits are for segments 15 to 17 and are ignored. (Note that the assignment of physical segments to segment numbers is complex due to bit-twiddling. see detpic/reverse.asm and layout/data2safety.) NMRADATA and NMRAFULL --------------------- The data bits in all of the bytes of the NMRADATA command (including the first) are simply transmitted as NMRA data to the track (most significant bit first). The top `end of packet' bit is not transmitted, though. The first 14 data bits in the NMRA packet should be 1s. (i.e. the first two complete bytes should be 11111111 11111111). Packets beginning with a different first byte are reserved for other commands to the PIC and the 14 idle bits are a requirement of the NMRA specification. The maximum NMRA message length is 15 bytes each carrying 7 bits of actual NMRA data (i.e. 105 bits). Up to three NMRADATA commands may be supplied by the host to the master PIC, and their will be transmitted in sequence. After each NMRADATA is completed, the PIC will send an NMRAFULL message to the host. In the NMRAFULL message, F is the number of completely-received NMRADATA commands awaiting transmission to the track. If the PIC runs out of NMRA data, it will transmit an NMRA idle stream. It is an error for the host to try to have more than three outstanding NMRADATA commands. DETECT ------ The DETECT command indicates to the host whether there is currently a train being detected at a specific location. The PIC must send a DETECT with Y=1 when a train is detected in a location where there was previously none, and with Y=0 when a train ceases to be detectable for more than a small amount of time. At HELLO, the host will assume that no trains are being detected. RAM (data) memory map ===================== The data memory map (for PIC18F458) looks like this: 0x000-0x05f Access bank RAM - RAM locations accessible via access bank instructions; also form part of RAM page 0 0x060-0x0ff Remainder of RAM page 0, accessible only via correct BSR setting (ie, BSR==0), INDF, etc. 0x100-0x1ff RAM page 1, accessible only via bank switching etc. 0x200-0x2ff RAM page 2, accessible only via bank switching etc. 0x300-0x3ff RAM page 3, accessible only via bank switching etc. 0x400-0x4ff RAM page 4, accessible only via bank switching etc. 0x500-0x5ff RAM page 5, accessible only via bank switching etc. 0x600-0xeff Nothing here, don't try to access. 0xf00-0xf5f SFR's (memory-mapped peripherals etc.) accessible only via correct BSR, INDF, etc - but these are only the CAN SFR's and we do not use the CAN controller. 0xf60-0xfff SFR's accessible via access bank (also form part of RAM page 15). See common.inc for actual uses of the RAM areas. Program (flash etc.) memory map =============================== Program memory map (for PIC18F458) looks like this: 0x00 0000- Program memory 0x00 7fff Contains actual program instructions and can also contain preprogrammed data provided via special .asm files. Notable contents and addresses: 0x00 0000 reset vector 0x00 0008 high-priority interrupt vector 0x00 0018 low-priority interrupt vector See common.inc for some special tables in here, for morse messages, pin/hardware-object definitions, etc. 0x20 0000- ID locations 0x20 0007 Programming which varies per PIC. Programmed by idlocs*.asm which are made by make-idlocs and included in perpic*.hex. Contents: 0x20 0000 bits 7-5 = 000 bits 4-0 = PIC number (guaranteed to be in the range 0..31 inclusive) 0x20 0001 bit 7 = 1 for the main PIC (#0) 0 otherwise bit 6 = 1 for Reversers board, 0 for Detectors bits 0-5 = currently unused, set to 0 0x20 0002- } not currently used, 0x20 0007 } may contain anything 0x30 0000- Hardware configuration 0x30 000f Defines (clock source, WDT operation, etc.) Probably best not to touch. `config.asm' provides correct contents, which is included in *-withcfg.hex and perpic*.hex. 0x3f fffe- Hardware device ID 0x3f ffff Fixed at manufacturing time; can be read to discover hardware type and version (probably not very useful) 0xf0 0000- EEPROM data area 0xf0 00ff Not currently used by us 0x01 0000- } These locations, not listed above, 0x1f ffff } do not correspond to anything - there 0x20 0008- } is no hardware or memory in the chip 0x2f ffff } at these locations. 0x30 0010- } 0x3f fffd } Accessing them isn't useful 0x40 0000- } and should probably be avoided. 0xef ffff } (Buffer page 50 0000h reserved for NMRA) XXXX these look wrong (Buffer page 40 0000h reserved for i2c) XXXX -iwj I2C === (slave addresses will be 10xxxxx where xxxxx=PIC number above)