Odd Parity Device and Hex Strings
Hey guys. I just got a device in that uses odd parity.
Quite some time ago Mike mentioned that to communicate bi-directionally using odd parity, the ASM section of FDS would need tweaking.
Anyone know if there is an existing obj that has a switch on it to manage odd? I went through the whole list today of objects and don't see a description of anything that relates.
Ideally, I want to use the 4xport Full Duplex object to save cogs as there are other serial coms, but would settle for anything just to get testing right away.
8 bits, odd par, 1 stop, least sig bit first.
Thanks
Quite some time ago Mike mentioned that to communicate bi-directionally using odd parity, the ASM section of FDS would need tweaking.
Anyone know if there is an existing obj that has a switch on it to manage odd? I went through the whole list today of objects and don't see a description of anything that relates.
Ideally, I want to use the 4xport Full Duplex object to save cogs as there are other serial coms, but would settle for anything just to get testing right away.
8 bits, odd par, 1 stop, least sig bit first.
Thanks
Comments
If it is 8bit odd par then the PASM will need changing. The tx code sends 10 bits - 1start, 8 bits, 1 stop. If you want to take a look at moding 4port serial, you probably can't mod all the ports, there isn't enough cog memory left.
This is the code you need to change. in particular txdata needs the 9th bit set to odd parity, before the shl instruction shown. This code is for the first port, similar code exists for each other port. Then change the last instruction to 12 bits.
rdbyte txdata,txbuff_tail_ptr '{8} add tx_tail,#1 and tx_tail,#$0F wz wrlong tx_tail,tx_tail_ptr '{8} if_z mov txbuff_tail_ptr,txbuff_ptr 'reset tail_ptr if we wrapped if_nz add txbuff_tail_ptr,#1 'otherwise add 1 jmpret txcode,rxcode1 shl txdata,#2 or txdata,txbitor 'ready byte to transmit mov txbits,#11
For the receive side
mov rxbits,#9 'ready to receive byte mov rxcnt,bit4_ticks '1/4 bits add rxcnt,cnt :bit add rxcnt,bit_ticks '1 bit period :wait jmpret rxcode,txcode 'run a chuck of transmit code, then return mov t1,rxcnt 'check if bit receive period done sub t1,cnt cmps t1,#0 wc if_nc jmp #:wait test rxmask,ina wc 'receive bit on rx pin rcr rxdata,#1 djnz rxbits,#:bit 'get remaining bits jmpret rxcode,txcode 'run a chunk of transmit code, then return shr rxdata,#32-9 'justify and trim received byte
Change the 9 in the first and last instruction to 10. This will not check partiy but just ignore it.
If you try to change the settings to even or none, the communication goes dead.
I will try to make sense of the changes you pointed out, thanks for posting that.
PRI oddParity(X) return (((X << 1) ^ (X << 2) ^ (X << 3) ^ (X << 4) ^ (X << 5) ^ (X << 6) ^ (X << 7)) & $80) | X
To transmit oddParity do: ser.tx(oddParity(char))
To check a received character for validity you can do: IF oddParity(char & $7F) == char
and txdata, #$ff wc 'generate odd parity mov t1,#0 rol t1,#9 'move c to 9th bit or txdata,t1 ...
First instruction sets c if there is an odd number of 1's in txdata, next 2 shift carry·to 9th bit·temp variable, last instruction or's it with txdata
Regards,
Ken
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
·"I have always wished that my computer would be as easy to use as my telephone.· My wish has come true.· I no longer know how to use my telephone."
- Bjarne Stroustrup
and txdata, #$ff wc 'generate odd parity
muxc txdata,$100 'set the 9th bit to parity
The receive path also checks the parity rather than just ignoring it.
02 D2 00 00
This is the string the devices debug test app uses to send to an inquiry to see if the device is working, and the device responds with another string
So I assumed I could do this:
serial.ser(string($02, $D2, $00,$00))
Yet I get the error on Run that says "string characters must range from 1-255" regarding the $00
What am I missing here?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
·"I have always wished that my computer would be as easy to use as my telephone.· My wish has come true.· I no longer know how to use my telephone."
- Bjarne Stroustrup
The basic commands contain $00 mixed in between other hex values.
Is it just the fact that FDS will not allow $00's, or the Prop in general?
So far I am not getting a response without the complete string being sent 0x02 0xD2 0x00 0x00
When I do this with the PC terminal they supply, the unit responds. But when I sent the truncated version 0x02 0xD2 there is no response.
Here is an example code:
//CommandStructure: Startbyte 0x02, index 0 , command 0x80, no payload
·m_CommandArray [noparse][[/noparse]0] = 0x02;
·m_CommandArray [noparse][[/noparse]1] = 0x00;
·m_CommandArray [noparse][[/noparse]2] = 0x00;
·m_CommandArray [noparse][[/noparse]3] = API_CAPTURE_IMAGE; //0x80;
·m_CommandArray [noparse][[/noparse]4] = 0x00;
·m_CommandArray [noparse][[/noparse]5] = 0x00;
·if (checkFingerPresent) m_CommandArray [noparse][[/noparse]3] = API_CAPTURE_IMAGE_FINGERPRESENT;
·if (!WriteFile(m_hComm, m_CommandArray, 6, &nWritten, NULL))
·{
··return FALSE;
·//CommandBuffer: Startbyte 0x02, no index, command 0x90, no payload
·m_CommandArray [noparse][[/noparse]0] = 0x02;
·m_CommandArray [noparse][[/noparse]1] = 0x01; //Will skip the CRC generation if set to 1.
·m_CommandArray [noparse][[/noparse]2] = 0x00;
·m_CommandArray [noparse][[/noparse]3] = API_UPLOAD_IMAGE; //0x90;
·m_CommandArray [noparse][[/noparse]4] = 0x00;
·m_CommandArray [noparse][[/noparse]5] = 0x00;
·//CommandStructure: Startbyte 0x02, no index, command 0x81, no payload
·m_CommandArray [noparse][[/noparse]0] = 0x02;
·m_CommandArray [noparse][[/noparse]1] = 0x00;
·m_CommandArray [noparse][[/noparse]2] = 0x00;
·m_CommandArray [noparse][[/noparse]3] = API_CAPTURE_AND_ENROL_RAM; //0x81;
·m_CommandArray [noparse][[/noparse]4] = 0x00;
·m_CommandArray [noparse][[/noparse]5] = 0x00;
// Response byte values·····HEX value
#define API_FAILURE······· 0x00
#define API_SUCCESS······0x01
Is there a substitute that may work to fill in the blank sections of the array on tx?· I will deal with the Rx as a secondary issue, since I just want to get the thing to respond via it's own debug for starters.·
Thanks for any suggestions
Post Edited (Originator) : 9/18/2008 4:14:48 AM GMT
PRI send(arrStr, len) | i
repeat i from 0 to len-1
serial.tx(byte[noparse][[/noparse]arrStr+i])
send(@m_CommandArray,6) will send 6 bytes of any value
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 TAB = $09 CR = $0D i2cSCL1 = 28 i2cSDA1 = 29 i2cSCL2 = 0 i2cSDA2 = 1 INT1PIN = 18 INT2PIN = 2 LCD_Pin = 7 LCD_Baud = 19200 LCD_Lines = 2 PCF8575_Addr = %0100_0000 SCANTXA = 3 SCANRXA = 4 SCANTXB = 5 SCANRXB = 6 HOMEPIN = 8 REFPIN = 9 FAULTPIN = 10 DIRPIN = 11 BRAKEPIN = 12 OPA = 13 OPB = 14 MP3TX = 15 MP3RX = 16 SETUPPIN = 17 BUZZERPIN = 19 CURRENTPIN = 20 ENCAPIN = 21 ENCBPIN = 22 TEMPPIN = 23 FOTXPIN = 24 FORXPIN = 25 VIBEPIN = 26 PWMPPIN = 27 SERTXPIN = 30 SERRXPIN = 31 VAR Byte TestHardWareArray[noparse][[/noparse]6] Byte ResponseArray[noparse][[/noparse]6] ' buffer for numeric fields long i2cAddress, i2cSlaveCounter 'byte semID 'long temp1, temp2 Byte recbyte LONG Pos OBJ serial : "FullDuplexSerial_Parity" 'serial : "Extended_FDSerial" 'LCD : "debug_lcd" 'i2c : "minimali2cdriver" 'pwm : "pwm" encoder : "Rotary Encoder" 'ser : "FullDuplexSerial" spk : "Piezospeaker.spin" 'beep(pin, freq, dur) 'UARTS : "pcFullDuplexSerial4FC" '1 COG for 4 serial ports PUB Init serial.start(26, 27, 0, 9600) 'ser.start(rxpin, txpin, mode, baudrate) : okay TestHardWareArray[noparse][[/noparse]0] := $02 TestHardWareArray[noparse][[/noparse]1] := $00 TestHardWareArray[noparse][[/noparse]2] := $00 TestHardWareArray[noparse][[/noparse]3] := $D2 TestHardWareArray[noparse][[/noparse]4] := $00 TestHardWareArray[noparse][[/noparse]5] := $00 repeat send(@TestHardWareArray,6) 'will send 6 bytes of any value receiveStr(@ResponseArray,5) if ResponseArray[noparse][[/noparse]0] == $02 spk.beep (15,2200,400)' if ResponseArray[noparse][[/noparse]1] == $10 spk.beep (15,2700,400) waitcnt(80_000_000 + cnt) PRI send(arrStr, len) | i repeat i from 0 to len-1 serial.tx(byte[noparse][[/noparse]arrStr+i]) PRI getrx recbyte := serial.rx PRI receiveStr(address,count) | c repeat count 'start counting c := serial.rx 'returns $00..$FF c = first rec'd byte if c == CR 'c == CR $0D byte[noparse][[/noparse]address] := 0 return c 'now return delimiter for optional checking byte[noparse][[/noparse]address++] := c 'update c return 0 'default delimiter is zero
Ok this is really messy test code but after many hours I have some steady response from the device back to the prop.· The responses aren't what I am expecting, but thats ok, at least they are talking.
The device wants hex in and out, I have no idea what I am really sending and receiving in the above code.·Since are just a few routines I need to send to it, I was thinking of setting up Arrays as shown that get loaded with the hex for each requirement, with corresponding names for the arrays.·
I feel that the parity must still be an issue, the device uses ODD.· I am testing with the FDP parity version that was posted earlier in the thread.
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 TAB = $09 CR = $0D VAR Byte TestHardWareArray[noparse][[/noparse]6] '6 Byte ResponseArray[noparse][[/noparse]4] OBJ serial : "FullDuplexSerial_Parity" spk : "Piezospeaker.spin" 'beep(pin, freq, dur) PUB Init TestHardWareArray[noparse][[/noparse]0] := $02 TestHardWareArray[noparse][[/noparse]1] := $00 TestHardWareArray[noparse][[/noparse]2] := $00 TestHardWareArray[noparse][[/noparse]3] := $D2 TestHardWareArray[noparse][[/noparse]4] := $00 TestHardWareArray[noparse][[/noparse]5] := $00 serial.start(26, 27, 5, 9600) 'ser.start(rxpin, txpin, mode, baudrate) : okay repeat send(@TestHardWareArray,6) 'will send 6 bytes of any value receiveStr(@ResponseArray,4) 'spk.beep(15,2000,400) if ResponseArray[noparse][[/noparse]0] == $02 'expected return value 1 spk.beep(15,2500,400) if ResponseArray[noparse][[/noparse]1] == $08 'expected return value 2 spk.beep (15,2600,400) if ResponseArray[noparse][[/noparse]2] == $00 'expected return value 3 spk.beep (15,2700,400)' if ResponseArray[noparse][[/noparse]3] == $00 'expected return value 4 spk.beep (15,2800,400) waitcnt(80_000_000 + cnt) waitcnt(80_000_000 + cnt) ResponseArray[noparse][[/noparse]0] := $FF 'change array to some different info ResponseArray[noparse][[/noparse]1] := $FF ResponseArray[noparse][[/noparse]2] := $FF ResponseArray[noparse][[/noparse]3] := $FF PRI send(arrStr, len) | i repeat i from 0 to len-1 'serial.str(byte[noparse][[/noparse]arrStr+i]) serial.hex(byte[noparse][[/noparse]arrstr+i],2) serial.tx(" ") PRI receiveStr(address,count) | c repeat count 'start counting c := serial.rx 'c = first rec'd byte if c == CR 'c == CR or TAB, byte[noparse][[/noparse]address] := 0 return c 'now return delimiter for optional checking byte[noparse][[/noparse]address++] := c 'update c return 0
I think it's time to roll up my sleeves and figure this out myself so I can know the fundamentals, but assembly is out of the question at the moment, so bit banging is the only thing I'll have time to deal with.
Can someone point me towards some learning resource to learn this serial comm stuff in a fast and practical way that applies to spin, so I can get an understanding and get this handled.
Thanks
CON _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 TAB = $09 CR = $0D LCD_Pin = 14 LCD_Baud = 9600 LCD_Lines = 2 VAR Byte TestHardWareArray[noparse][[/noparse]7] '6 Byte ResponseArray[noparse][[/noparse]5] OBJ ser : "FullDuplexSerial4PortParity" spk : "Piezospeaker.spin" 'beep(pin, freq, dur) LCD : "debug_lcd" PUB Init ser.init Ser.AddPort(0,26,27,-1,-1,0,0,9600) Ser.Start TestHardWareArray[noparse][[/noparse]0] := $02 TestHardWareArray[noparse][[/noparse]1] := $00 TestHardWareArray[noparse][[/noparse]2] := $00 TestHardWareArray[noparse][[/noparse]3] := $D2 TestHardWareArray[noparse][[/noparse]4] := $00 TestHardWareArray[noparse][[/noparse]5] := $00 if lcd.start(LCD_PIN, LCD_BAUD, LCD_LINES) ' start lcd lcd.cursor(0) ' cursor off lcd.backLight(true) ' backlight on (if available) lcd.cls ' clear the lcd lcd.str(string("Initializing...")) waitcnt(40_000_000 + cnt) lcd.cls repeat Send(@TestHardWareArray, 6) receiveStr(@ResponseArray,4) DisplayResponse waitcnt(80_000_000 + cnt) PUB DisplayResponse lcd.cls lcd.hex(ResponseArray[noparse][[/noparse]0], 2) lcd.str(string(" ")) lcd.hex(ResponseArray[noparse][[/noparse]1], 2) lcd.str(string(" ")) lcd.hex(ResponseArray[noparse][[/noparse]2], 2) lcd.str(string(" ")) lcd.hex(ResponseArray[noparse][[/noparse]3], 2) lcd.str(string(" ")) PRI send(arrStr, len) | i repeat i from 0 to len-1 'ser.str(byte[noparse][[/noparse]arrStr+i]) ser.hex(0,byte[noparse][[/noparse]arrstr+i],2) ser.tx(0," ") PRI receiveStr(address,count) | c repeat count 'start counting c := ser.rx(0) 'c = first rec'd byte if c == CR 'c == CR or TAB, byte[noparse][[/noparse]address] := 0 return c 'now return delimiter for optional checking byte[noparse][[/noparse]address++] := c 'update c return 0
PRI send ser.tx(0,$02) 'start byte ser.tx(0,$00) 'unused ser.tx(0,$00) 'unused ser.tx(0,$D2) 'HW test ser.tx(0,$00) 'unused ser.tx(0,$00) 'unused
The·first I have seen the Hardware Test OK·response so far!
02 08 00 00
02 is the response start byte, 08 is HWare·OK
There is a pattern:
success
fail
success
fail
fail
success
repeat
Very close though.· Thanks Tim for that mod.
Post Edited (Originator) : 9/19/2008 8:02:05 AM GMT
2 things to look at about the failures.
1. Are you always sending the same message. If no calculate the parity by hand. Does the parity change, if so it could mean theres a problem with the parity generation
2. Is there a terminating char when you send, e.g. are you meant ot send a CR or LF or both after sending the command sequence?
No, there will be maybe 10-15 standard messages. I am send the test as just one string that never changes.
2. Is there a terminating char when you send, e.g. are you meant to send a CR or LF or both after sending the command sequence?
No there are no terminations sent, just 4 bytes starting with 02
Thanks for taking a look at it.
Post Edited (Originator) : 9/19/2008 7:38:03 PM GMT
What exactly is printed out when it fails, if the device sends CR,LF then its going to affect the next response. i.e. teh next response will have the 02 offset and a different hex printed out for the first hex number
I found the error!
This is what I was really doing to produce the inconsistent response after the parity issue was finally resolved with adapted 4port:
PRI send
Repeat
ser.tx(0,$02) 'start byte
ser.tx(0,$00) 'unused
ser.tx(0,$00) 'unused
ser.tx(0,$D2) 'HW test
ser.tx(0,$00) 'unused
ser.tx(0,$00) 'unused
The 'repeat' is the problem, remove it and 100% accuracy.
I had modified the PUB Send from earlier that used the repeat and forgot to take out the repeat line.
For some strange reason, only when I use the 6 separate lines of TX does it respond, no variation of ser.tx, ser.hex, ser.str works, only the 6 separate lines.
In any case, this is working.
The following should work as well, if you fill the array how you did before.
PRI send(arrStr, len) | i repeat i from 0 to len-1 ser.tx(byte[noparse][[/noparse]arrStr+i])
Thanks for the 4 port serial object - it works great.. Just wondering if you can help me with a small problem though. I'm playing with a Lassen iQ GPS receiver which uses 9600,8,ODD,1. I am using your modified version of the serial object which has port 0 as default ODD parity. This works great for receiving data from the GPS but I cant seem to get it to work TXing to the GPS. I think the problem may be that when TX completes a byte, the TX line stays LOW - as compared to the GPS output which leaves the TX line HIGH. See attached picture - the upper trace is the propeller output to the GPS and the lower one is the output from the GPS. I have spent a fair amount of time looking at your code to see where it can be modified without much success unfortunately. The other possibility is that I am missing something entirely obvious of course! Help with this problem would be much appreciated.
Thanks in advance,
S
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
News Flash!... Energizer Bunny arrested and charged with battery.
I am guessing it is something else being overlooked.
Post Edited (Originator) : 11/9/2008 8:43:55 AM GMT