|
 |
|
03-23-2005, 04:05 AM
|
#1
|
|
Variable Bitrate
Join Date: Oct 2003
Location: Chicago, IL
Posts: 284
|
Need help decoding a one wire databus...
Hey guys,
this is going to be a very long and detailed post because I would like to make myself clear as possible. No cliff notes
I am trying to integrate the navigation controls from the Mazda RX-8 into my setup. I have the unit and I've figured out a sort of pinout of the connector:
Code:
Mazda RX-8 Car Navigation Switch Pinout
O M K I G E C A
* * AA BB PWR * * *
* * BUS ILL GND * * *
P N L J H F D B
PWR = Power +12V
GND = Ground
ILL = Illumination (+12V)
BUS = Data Bus
AA = Unknown (Always High)
BB = Unknown (Always Low)
With this information, I put the data bus on my logic analyzer and got these waveforms:

This is a full data transaction.
Line goes low for ~9ms, then high for ~4.5ms. There is a .5ms pulse between each "bit". The longer "bit" (which i guess is 1?) is ~1.5ms (so 3 times the timing pulse...). The shorter "bit" is .5ms also.
After decoding all the keys ive come up with this: (does not include the ~9ms low, ~4.5ms high part)
Code:
Control
/-------------------------------------------------------------|
|Menu Button - 1000 0001 0101 0111 0011 0000 1100 1111|
|Voice Button - 1000 0001 0101 0111 0111 0000 1000 1111|
|Ret Button - 1000 0001 0101 0111 1001 0000 0110 1111|
|Pos Button - 1000 0001 0101 0111 1011 0000 0100 1111|
|Zoom-in Button - 1000 0001 0101 0111 1101 0000 0010 1111|
|Zoom-out Button - 1000 0001 0101 0111 0101 0000 1010 1111|
|Enter Button - 1000 0001 0101 0111 0001 0000 1110 1111|
|Joystick Up - 1000 0001 0101 0111 1100 0000 0011 1111|
|Joystick Down - 1000 0001 0101 0111 0000 0000 1111 1111|
|Joystick Left - 1000 0001 0101 0111 0100 0000 1011 1111|
|Joystick Right - 1000 0001 0101 0111 1000 0000 0111 1111|
|Joystick Up+Left - 1000 0001 0101 0111 0110 0000 1001 1111|
|Joystick Up+Right - 1000 0001 0101 0111 1110 0000 0001 1111|
|Joystick Down+Left - 1000 0001 0101 0111 1010 0000 0101 1111|
|Joystick Down+Right - 1000 0001 0101 0111 0010 0000 1101 1111|
\-------------------------------------------------------------/
In addition, I came across this site: http://mazda.davidoshea.homelinux.net/radio/bus.html
which documents decoding the Mazda3 Radio bus. While similar, this Mazda3 bus is more variable PWM (bit+pulse always = constant timing, whereas with this bus, bit+pulse could either be 1ms - 2ms). It seems to definetly have some sort of protocol going on here. Which *kinda* maps up to the protocol shown on the Mazda3 radio page.
I've been googling for some time to see if this pattern matches up something already existing. I can't seem to find anything to help make this easier.
For right now, I'm just trying to get this data nicely into a PIC.
Here is some pseudocodish stuff ive come up with:
Code:
check if bus is low, if not wait
bus low? yes, now wait till it goes high again...
bus high? k now wait the 4.5 ms and go into bit collecting routine:
bit collecting
wait .5ms
bus high? add to counter
wait .5ms
bus high? add to counter
bus low? drop out (counter would be 1 if bit was low)
wait .5 ms
bus high? add to counter (counter would now be 3 if the bit was high)
bus low? drop out
wait .5ms
bus high? drop out (it shouldnt be high for 2ms)
decrease counter, skip next command if zero (if its a LOW bit, next command will be executed...)
move 0 bit into variable
move 1 bit into variable
go back to bit collecting
im sure some timing things have been left out but this is the best ive come up with at the moment that seems like it should work kinda okay. I wanted to post this up here and ask for any help or guidance on this little project if anyone is interested. I'm fairly intermediate with PICs, I've done some work with I2C and RS232, so dont be afraid to just throw stuff out there without having to hold my hand.
Thanks for any help or info you could provide,
bryan
__________________
Mazdaspeed Car Computer
gotta redo it all
|
|
|
|
|
|
Advertisement
|
Sponsored links
|
03-23-2005, 04:42 AM
|
#2
|
|
Constant Bitrate
Join Date: Oct 2003
Location: ACT, Australia
Posts: 114
|
That's a pretty cool project you got going on there ...
One thing I could provide you is some optimisation for your firmware. Your method of decoding is referred to as polling, which can be inefficient if your PIC needs to do other processing.
Now if you're like me you'd say nah polling will work and I won't need the PIC to do other things, but I think i've grown now to realise go efficient from the start.
Anyways to the point. You would be best to setup an interrupt routine for your bit collecting. You've already done the hardwork by collecting and decoding the signals your after. You would set your interrupt to trigger on rising/falling edges and simply calculate the time between successive triggers.
Using this method you can decode the signals by:
1. detecting the 9ms low/4.5ms high sequence indicating the start of a code sequence.
2. once a code sequence is detected you then calculate for the next 32 rising/falling edges.
3. If time between sucessive rising/falling edges is ~.5ms it's a zero, otherwise it's a one.
4. Once 32 bits have been collected then you can set a flag to indicate you have a valid code for the program to decode.
This should improve the efficiency of your code, I use this technique a lot for decoding signals of this variety. Hope this helps
__________________
Caputer Mk. II
'02 VX Holden Commodore Series II Executive
MII12000, 512MB RAM, 60GB HDD (5400rpm), 16X DVD, TS200V
Morex 60W DC-DC, Custom S/SDC
OS/Software: Developing...
|
|
|
03-23-2005, 09:54 AM
|
#3
|
|
Raw Wave
Join Date: Mar 2004
Location: Redondo Beach, CA
Posts: 1,969
|
The interrupt based approach seems easier to me. Also, if your pic has a PWM, I belive it can be used to trigger on an edge and capture the clock all in one shot -- to improve the stability of your measurements a little.
In looking at the code, there are really only 4 bits needed to detect which button is pressed. Isn't there a 1111 (or 0000 for the inverted 4 bits) code that you receive for when the button is released; or does the bit pattern repeated continuously while the button is down? Or is this the sequence for a button press and release?
Knowing that only 4 bits are needed, you could optimize the detection routine to only save 4 bits. Whenever those bits are 0111, the next 4 bits are the ones you need -- of course this assumes that the patterns you've shown are all that will ever be on the bus; I dunno if that's true or not.
Good luck!
Last edited by rando; 03-23-2005 at 10:06 AM.
|
|
|
03-23-2005, 10:04 AM
|
#4
|
|
Raw Wave
Join Date: Mar 2004
Location: Redondo Beach, CA
Posts: 1,969
|
So the pattern looks like this
1000 0001 0101 0111 KC 0000 KC# 1111
or
8157K0k1
Where k = ~K
and K is the keypress code defined below
0 D
1 Enter
2 DR
3 Menu
4 L
5 Zoom-out
6 UL
7 Voice
8 R
9 Ret
A DL
B Pos
C U
D Zoom-in
E UR
Last edited by rando; 03-23-2005 at 10:10 AM.
|
|
|
03-23-2005, 07:07 PM
|
#5
|
|
Variable Bitrate
Join Date: Oct 2003
Location: Chicago, IL
Posts: 284
|
Quote: Originally Posted by rando
The interrupt based approach seems easier to me. Also, if your pic has a PWM, I belive it can be used to trigger on an edge and capture the clock all in one shot -- to improve the stability of your measurements a little.
In looking at the code, there are really only 4 bits needed to detect which button is pressed. Isn't there a 1111 (or 0000 for the inverted 4 bits) code that you receive for when the button is released; or does the bit pattern repeated continuously while the button is down? Or is this the sequence for a button press and release?
Knowing that only 4 bits are needed, you could optimize the detection routine to only save 4 bits. Whenever those bits are 0111, the next 4 bits are the ones you need -- of course this assumes that the patterns you've shown are all that will ever be on the bus; I dunno if that's true or not.
Good luck!
My PIC I will be doing testing with is a 16F628 or 16F877. Eventually I'd like to get it onto a USB PIC (not sure which one yet).
And yeah, I did notice I would only need to really save those 4 bits, as it will uniquely idenify the action. This will be the only device on the bus. I'm not planning on interfacing with any other OEM harware. But in order to perhaps make the code reusable for other hardware, I think I will process and save all bits.
This pattern is generated for a button press and release. If the button is held down, the pattern repeats itself after a pause of roughly 25ms. So after a stream is collected, I can just to back to my "wait if bus is low, wait 9ms..." routine.
Do you by chance have any more info on this PWM method? I searched for awhile but all I came up with was info on programming FPGAs. Right now, I'm trying to figure out how to implement OdysseyPC's code. I've never used timers before so I'm trying to pick that up and figure it out.
Much thanks for the response, this really helps alot!
__________________
Mazdaspeed Car Computer
gotta redo it all
|
|
|
03-23-2005, 07:10 PM
|
#6
|
|
Variable Bitrate
Join Date: Oct 2003
Location: Chicago, IL
Posts: 284
|
Quote: Originally Posted by OdysseyPC
That's a pretty cool project you got going on there ...
One thing I could provide you is some optimisation for your firmware. Your method of decoding is referred to as polling, which can be inefficient if your PIC needs to do other processing.
Now if you're like me you'd say nah polling will work and I won't need the PIC to do other things, but I think i've grown now to realise go efficient from the start.
Anyways to the point. You would be best to setup an interrupt routine for your bit collecting. You've already done the hardwork by collecting and decoding the signals your after. You would set your interrupt to trigger on rising/falling edges and simply calculate the time between successive triggers.
Using this method you can decode the signals by:
1. detecting the 9ms low/4.5ms high sequence indicating the start of a code sequence.
2. once a code sequence is detected you then calculate for the next 32 rising/falling edges.
3. If time between sucessive rising/falling edges is ~.5ms it's a zero, otherwise it's a one.
4. Once 32 bits have been collected then you can set a flag to indicate you have a valid code for the program to decode.
This should improve the efficiency of your code, I use this technique a lot for decoding signals of this variety. Hope this helps
Thanks! This method does seem better that polling. I've used interrupts before but never the timer/counter. I will continue reading up on this stuff and figuring it out. Thanks again.
__________________
Mazdaspeed Car Computer
gotta redo it all
|
|
|
03-23-2005, 07:58 PM
|
#7
|
|
Raw Wave
Join Date: May 2003
Posts: 2,021
|
The PWM being mentioned is the CCP module. This can be setup to time the pulse width and return the value in the CCP registers, useful for measuring the pulse width.
Hmm interrupts? I wont bother with it. The bit change interrupt can be a problem when at the same time trying to access the port, very unlikely you be doing this anyway.
From microchip apps note >
Note: If a change on the I/O pin should occur
when a read operation is being executed
(start of the Q2 cycle), then the RBIF
interrupt flag may not get set.
The interrupt-on-change feature is recommended for
wake-up on key depression operation and operations
where PORTB is only used for the interrupt-on-change
feature. Polling of PORTB is not recommended while
using the interrupt-on-change feature.
Applying interrupt, your code wont be doing anything apart from waiting for the line to go low for ~9ms then back high again for ~5ms to indicate a start condition. Once you are in the start theres not much for you to do apart from decoding the stream of data which is going to be part of the interrupt routine.
Your main will look like >
Main
goto main
Look abit silly. The rest are done in the interrupt routine.
As for the CCP module, not all PICs have this. Infact you dont even need it.
If you really want to optimise your design, use a 12C508 or something along those line.
For measuring the pulse width you can make it this way >
Setup a 0.1ms timer that set a flag every 0.1ms using interrupts.
On part of the decoding routine on the main >
Each time an interrupt occured a counter is incremented. If this counter contains ~5 after a bit changed then you know ~0.5ms has passed. You reset this counter every bit change and of course you have to reset the "0.1ms" elapsed flag every time you increment.
You now have a pulse width measurement routine accurate to ~0.1ms.
So from the beginning, your main loop will start incrementing the pulse width counter as soon as a LOW is detected. If the counter does not equate to ~9ms after it goes high then you know this is not a start condition, the code should reset looking for the ~9ms LOW again. If successful, look for a ~5ms high this time.
All you have to do is keep a track of the pulse width counter and at which state it is measuring, a HIGH or a LOW state. From there you can decode on the fly.
You can either save all the data and decode from the RAM or just decode whats needed on the fly.
How are you going to output the decoded bits? Using 4 pins from the PIC or output it to the serial port?
Outputing it to serial port should be fairly easy.
How you gonna program it? ASM? C? BASIC?
Interrupt or polling, hardware or software pulse width measurement thats your choice. But this little project can definitely be done with some of the most basic PIC you can buy.
Thats about it for now I guess
Last edited by Chris31; 03-23-2005 at 08:14 PM.
|
|
|
03-23-2005, 08:15 PM
|
#8
|
|
Raw Wave
Join Date: May 2003
Posts: 2,021
|
If I missed something, thats because I havent read the thread in details
|
|
|
03-23-2005, 08:21 PM
|
#9
|
|
Variable Bitrate
Join Date: Oct 2003
Location: Chicago, IL
Posts: 284
|
Wow, at least i can answer the last two questions
ASM and serial output
Thanks! let me try to digest all of that.
__________________
Mazdaspeed Car Computer
gotta redo it all
|
|
|
03-23-2005, 08:26 PM
|
#10
|
|
Variable Bitrate
Join Date: Aug 2004
Posts: 313
|
cool thread - I'll buy a board + try the software when it's done!
|
|
|
03-23-2005, 08:34 PM
|
#11
|
|
Variable Bitrate
Join Date: Oct 2003
Location: Chicago, IL
Posts: 284
|
Quote: Originally Posted by Chris31
If I missed something, thats because I havent read the thread in details 
Chris31, with your code idea, i would have to wait until im "inside" the frame for data, correct? You know what i mean? I dont want to be exactly right on the rising/falling edge, so i would have to pay more attention to timing detail. I wont be using the PIC for anything other than taking the data from the controls and moving it to PC, so I would not use the pin for output or anything else.
Are you still sure interrupts would not be a good idea for simplicity sake? Im not criticizing, just wondering.
__________________
Mazdaspeed Car Computer
gotta redo it all
|
|
|
03-23-2005, 08:36 PM
|
#12
|
|
Raw Wave
Join Date: May 2003
Posts: 2,021
|
Quote: Originally Posted by Dexter
Wow, at least i can answer the last two questions
ASM and serial output
Thanks! let me try to digest all of that. 
 you asked for it
Ok just to add more stuff, the CCP module, you can set it to either measure the width of every rising edge or every falling edge. Thats not good for you as you will need to measure the width of the HIGH and the LOW of the stream in real time.
You need the HIGH measurement for the >
High start condition ~5ms
High bit ~1.5ms
You need the LOW measurement for the >
Low start condition ~9ms
Low bit ~1ms
Bit space ~0.5ms
Oh take your time digesting it
|
|
|
03-23-2005, 08:46 PM
|
#13
|
|
Raw Wave
Join Date: May 2003
Posts: 2,021
|
Well, the CCP maybe out of the question now. There may be a way around it, as I said from the above post you do need to measure the width of the LOW and the HIGH so you can recognise every part of the stream. I dont think you can do that with the CCP module, although you can switch mode >
bit 3-0 CCP1M3:CCP1M0: CCP1 Mode Select bits
0000 = Capture/Compare/PWM disabled (resets CCP1 module)
0100 = Capture mode, every falling edge
0101 = Capture mode, every rising edg
Because you are measuring the width in real time, I dont think the CCP module will be happy switching mode and expect it to do its job properly.
With the interrupt, sure you can do it why not.
But what are you going to do when you have an interrupt on bit change? That interrupt cannot distinguish if it was a transistion from HIGH to LOW or from LOW to HIGH. All it will do is interrupt when theres a change on that pin. You will still need to recognise its current state, in that case you still end up reading the state of that pin. If another interrupt occur while reading that pin then you can have a problem, as been noted by microchip.
I have been stung with this before and it was a PITA to debug. All I was doing is to detect a key press using interrupts...yay. I got it working eventually.
Last edited by Chris31; 03-23-2005 at 09:13 PM.
|
|
|
03-23-2005, 08:53 PM
|
#14
|
|
Variable Bitrate
Join Date: Oct 2003
Location: Chicago, IL
Posts: 284
|
Quote: Originally Posted by Chris31
bit 3-0 CCP1M3:CCP1M0: CCP1 Mode Select bits
0000 = Capture/Compare/PWM disabled (resets CCP1 module)
0100 = Capture mode, every falling edge
0101 = Capture mode, every rising edge
I understand what you are saying abot the CCP now. I could switch to 0101, capture rising edge, then switch to 0100 and capture falling edge, but it may not like that fast switching.
Quote: Originally Posted by Chris31
I have been stung with this before and it was a PITA to debug.
Lovely.
Thanks a ton for all of this. And for your time for posting all that.
__________________
Mazdaspeed Car Computer
gotta redo it all
|
|
|
03-23-2005, 08:56 PM
|
#15
|
|
Variable Bitrate
Join Date: Apr 2004
Posts: 228
|
Wow. That protocol is exactly the same one that was used by the head unit to communicate with the CD changer in my Audi, which was a panasonic or matsushista (sp?) unit.
When I was doing my initial research I found this information:
Quote:
The protocol panasonic uses is of the serial sync. type. There is one data line, a clock line and a sync line the changer uses to send data to the radio.
The radio to changer communication is done by some signals known from standard IR remote controls (without a carrier) using one dataline.
This remote control signal is pulse width modulated,the dataline is active high.
After an initail high(9ms) low(4.5ms) there follows a 32 bit sequence with a 0 encoded as 550us high,550us low and a 1 as 550us high,1.7ms low.
If the low pulse in the init phase is only 2.25ms long it is just a signal send periodical when a key is hold down and there are no data bits.
The data is transfered lsb first, the 1st byte is 0xFF-0th byte and the 3rd byte is 0xFE-2nd byte.The 2nd byte is the command.
The changer to radio communication transfers the data in bytes msb first, the data is valid at the falling clock edge and a low pulse of one half clock period is sent after the first and the last byte of the transfer on the sync line..The clock period is arround 8us.
There was only one packet containing state, time, disc and track information.
I do remember something about that description not being exactly right (I think having to do with the ordering of the bytes between LSB and MSB). I was going to take a circuit to a working product and hoped to make a little money off of it but I ended up having to head off to Germany and I sold my Audi when I got back.
I ended up accomplishing it with a polling routine first as proof of concept only because I couldn't get the pulse capture to behave right. Fortunately, the bit information is coded always with the high pulse first so the polling routine was easy to "lock on" to the signal.
If you want I can dig up some more information on it but it seems like you are almost there as it is.
|
|
|
|
Sponsored links
|
|
Advertisement
|
|
| Thread Tools |
|
|
| Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -5. The time now is 08:22 PM.
| |