CON {{ Modified Serial Communication for 8.42 Meg Baud Propeller to Propeller Communication: Note: - Put 10k pull down resistor on rx line. - Tests were performed using a two conductor #24 ribbon cable carrying GND and Signal with a cable length of 10 feet. - Over 100 Billion data bits were sent with Zero reported packet errors. The Serial Data Stream is organized as follows: 2 Start Bits / 32 Data Bits / 1 Stop Bit Each Start Bit is 1/2 the normal Bit Width ; Normal Bit Width is 100nS MSB(31) LSB(0) 450uS (Read/Write - overhead)    ...    │ Start2 - LOW(50nS) Stop - LOW (50nS + 450nS overhead) Start1 - HIGH(50nS │───────────────────────────────── 3800nS ────────────────────────────────────│ At 3800nS per long(32-Bits), or 263.158kHz per long, the average bit rate is about 8.42MHz You may ask... Why 2 Start Bits. It's easier explained visually if you represent the clock ticks like this... Each clock tick represents 12.5nS Start bit #2 begins read here  11112222dddddddd <- Beginning of Serial Data Stream   │ Data begins read here │ Start bit #1 begins read here 1 - Start Bit 1 2 - Start Bit 2 d - data The 'waitpeq' instruction takes 5 clocks to read the pin and exit... it actually determines the state on the first clock tick that the condition is true, but takes an additional 4 clocks to exit. This places us 1 clock tick into the second Start Bit before we even begin to look at it. This actually works out to our benefit. The 'waitpne' instruction also takes 5 clocks to read the pin and exit... likewise it also determines the state on the first clock tick that the condition is true, but takes an additional 4 clocks to exit. After two of these type of instructions we automatically have an offset of 2 clocks or 25nS locked to the Transmitter. What this does, is eliminate the possibility of sampling the signal on a transition edge where it can be very noisy. Since the Transmitter is ultimately creating the Start Bits, an absolute reference lock between the transmitter and receiver is established on every transmitted LONG variable. }} _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 RX_Pin = 17 '8.42 meg baud rx pin *use 10k pull down. TX_Pin = 16 '8.42 meg baud tx pin PacketSize = 1 '<- Number of Packet Longs to receive ; 1 Long = 32 data Bits DiagRX = 31 'diagnostic rx DiagTX = 30 'diagnostic tx VAR long cogon[5], cog[5], pile[500] long DataIn[PacketSize],ReadyFlag '<-ReadyFlag must follow immediately after the Data long DataOut[PacketSize] long match, error OBJ Diag : "FullDuplexSerialPlus" PUB Start stop cogon[0] := (cog[0] := cognew(TxPropeller, @pile[0]) > 0) '2 cogs cogon[1] := (cog[1] := cognew(RxPropeller, @pile[100]) > 0) '2 cogs 'cogon[2] := (cog[2] := cognew(unused, @pile[200]) > 0) 'cogon[3] := (cog[3] := cognew(unused, @pile[300]) > 0) 'cogon[4] := (cog[4] := cognew(Unused, @pile[400]) > 0) '----DIAGNOSTIC------ cogon[4] := (cog[4] := cognew(DiagGo, @pile[400]) > 0) ' 2 cogs PUB RXPropeller|i, Flag,SeedRx,OldError,OldMatch OldError := -2 'Initialize variable states Error := -1 repeat RX(@DataIn) 'Read and wait here for Data Packet SeedRx := $1234_5678 'For DEBUG only ; Generates pseudo Random Data to compare 'against the data received. 'Note: The Transmitter MUST have the same Seed value Flag := 0 repeat i from 0 to PacketSize-1 'Check Data and update display only if there is a difference if DataIn[i] <> ?SeedRx 'in the number of Matches or the number of Errors Flag := 1 if Flag == 0 Match += 1 if Flag == 1 Error += 1 PUB RX(_DataIn) ReadyFlag := 1 'Read Data cognew(@RX_Propeller_COM,_DataIn) repeat while ReadyFlag == 1 'Wait here until data is ready PUB TXPropeller|i,SeedTx SeedTx := $1234_5678 'For DEBUG only ; Generates pseudo Random Data to send repeat i from 0 to PacketSize -1 'Note: The Receiver MUST have the same Seed value DataOut[i] := ?SeedTx repeat 'Continuously send Data Packet TX(@DataOut) 'Transmit Data Packet waitcnt(800_000+cnt) '<--- Wait for Receiver to Process and Display Data before next transmission 'Note: This value is subject to change depending on your program on the receive ' side... there is no handshaking, in other words, the receiver must be ' ready and waiting BEFORE you transmit data or data will be lost. PUB TX(_DataOut) cognew(@TX_Propeller_COM,_DataOut) 'Send Data Pub DiagGo Diag.start(DiagRX, DiagTX, 0, 115200) Repeat waitcnt(10_000_000 + cnt) 'Wait for 1000 ms or 1 second 'DiagComm.str(string(1)) 'home diag.str(string(16)) 'clear screen diag.str(string("Matched Packets:")) diag.dec(Match) diag.str(string(9)) 'TAB diag.str(string("Error Packets:")) diag.dec(Error) PUB stop '' Unload timer object - frees a cog if cogon[0]~ ' if object running, mark stopped cogstop(cog[0]) if cogon[1]~ ' if object running, mark stopped cogstop(cog[1]) if cogon[2]~ ' if object running, mark stopped cogstop(cog[2]) if cogon[3]~ ' if object running, mark stopped cogstop(cog[3]) if cogon[4]~ ' if object running, mark stopped cogstop(cog[4]) DAT org 0 RX_Propeller_COM mov DataIndexRx, par 'Read Data Location into DataIndex mov RX_PinMask, #1 'Create Pin Mask for Input/Output pin shl RX_PinMask, #RX_Pin SYNC_Start waitpeq RX_PinMask, RX_PinMask 'Wait for SYNC - HIGH waitpne RX_PinMask, RX_PinMask 'Wait for SYNC - LOW test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 test RX_PinMask, ina wc 'Read RX pin into "C" rcl BuffRx,#1 'Rotate Buff left and place "C" in Bit0 wrlong BuffRx, DataIndexRx'Write Data Value to Indexed location add DataIndexRx, #4 'Increment Index value djnz DataSamplesRx, #SYNC_Start'Check to see if there are more data samples mov tempRx, #0 'Clear the Ready Flag wrlong tempRx, DataIndexRx cogid tempRx 'Get this COG ID cogstop tempRx 'STOP this COG 'initialized variables DataSamplesRx long PacketSize 'uninitialized variables DataIndexRx long 0 BuffRx long 0 'aliased variables tempRx RX_PinMask long 0 fit org 0 TX_Propeller_COM mov TX_PinMask, #1 'Create Pin Mask for Input/Output pin shl TX_PinMask, #TX_Pin andn outa, TX_PinMask 'Preset Pin LOW or dira, TX_PinMask 'Make Pin an Output LOW mov DataIndexTx, par 'Read Data Location into DataIndex LoadData rdlong BuffTx, DataIndexTx 'Read Data Value from Indexed location add DataIndexTx, #4 'Increment Index value nop rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 or outa, TX_PinMask 'Make Pin HIGH (50nS) SYNC andn outa, TX_PinMask 'Make Pin LOW (50nS) SYNC muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA rol BuffTx, #1 wc 'Read BuffTx Bit31 into "C" ; Rotate BuffTx left by 1 muxc outa, TX_PinMask 'Make Pin HIGH or LOW (100nS) DATA nop andn outa, TX_PinMask 'Make Pin LOW (750nS) djnz DataSamplesTx, #LoadData 'Check to see if there are more data samples andn dira, TX_PinMask 'Make Pin an Input cogid tempTx 'Get this COG ID cogstop tempTx 'STOP this COG 'initialized variables DataSamplesTx long PacketSize 'un-initialized variables DataIndexTx long 0 BuffTx long 0 'aliased variables tempTx TX_PinMask long 0 fit