![]() |
|||||
Home |
The Nokia NRC-17 protocol transmits 16 real bits per message.
Therefore all data will be shown in hexadecimal format on the PIC IR Receiver.
NRC-17 will send a start message when you press a button on the remote, and a stop message when you release the button again.
In between the actual message belonging to that particular key is transmitted repeatedly.
These start and stop messages have the sub-code/address/command code $FFFE.
A particular property of the NRC-17 protocol is the fact that it can signal low battery level to the receiver. The receiver can than warn the user that it is time to replace the batteries of the remote. On the PIC IR Decoder a low battery indication is shown by the right most decimal point.
In my knowledge base you can read that the NRC-17 protocol uses bi-phase modulation of the IR carrier to transmit a total of 17 bits. A bi-phase modulated bit can be thought of as two separate bits which are always the inverse of each other. A logical zero is represented by a "10" pattern on the IR input, while a logical one is represented by a "01" pattern. That is basically what we're going to use to decode the received message.
The IR decoding software relies on a state machine, which is described in detail on the RC-5 page. Two extra states have been placed in between the RC-5 states to test the width of the gap between the start pulse and the first data pulse. For the rest there are only minor changes. ;-----------------------------------------------------------------------------
;
; IR receiver state machine
;
;-----------------------------------------------------------------------------
IR_MACHINE MOVF IR_STATE,W Jump to present state
MOVWF PCL
No changes here, compared to the RC-5 decoder software. Again this routine is called every 50 µs and will immediately jump to the current state routine. ;---------------------------------------STATE 0, WAIT FOR BEGIN OF START BIT--
IR_STATE_0 BTFSC PORTA,4 Input still high?
RETURN Yes! Nothing to do
MOVLW HALF_TIME/2 Wait until we're in the center of the
MOVWF BIT_TIMER pre-pulse
MOVLW IR_STATE_1 Next stop is state 1
MOVWF IR_STATE
RETURN
This state is also identical to the RC-5 decoder's IR_STATE_0. The only difference is not obvious from this code because it only involves the value of HALF_TIME, which is adapted to the different pulse width of the NRC-17 code. ;---------------------------STATE 1, START BIT DETECTED, CHECK IF IT IS REAL--
IR_STATE_1 DECFSZ BIT_TIMER Wait until center of pre-pulse
RETURN Time's not up yet!
BTFSC PORTA,4 Is the input still low?
GOTO IR_ERROR_1 Nope! Exit with error
MOVLW HALF_TIME Set interval to half a bit time
MOVWF BIT_TIMER
MOVLW 5 Next 5 samples must be high!
MOVWF IR_SHIFT
MOVLW IR_STATE_2 Which is checked next
MOVWF IR_STATE
RETURN
Here is another difference between the RC-5 decoder software. We are now expecting a pause of 2.5 bit times, or 3.5 bit times in case the battery is empty. Therefore we don't initialize the shift register yet. IR_SHIFT is now abused as a half-bit counter which will cause us to wait 5 half-bit times in state 2. ;-------------------STATE 2, PRE_PULSE DETECTED, NEXT 5 SAMPLES MUST BE HIGH--
IR_STATE_2 DECFSZ BIT_TIMER Wait until center of half bit
RETURN Time's not up yet!
BTFSS PORTA,4 Is input high?
GOTO IR_ERROR_0 Nope! Exit with error
MOVLW HALF_TIME Set interval to half a bit time again
MOVWF BIT_TIMER
DECFSZ IR_SHIFT Decrement counter
RETURN Counter <> 0, don't change state yet!
MOVLW IR_STATE_3 Go to next state
MOVWF IR_STATE
CLRF IR_SHIFT Prepare shift register
CLRF IR_SHIFT+1
RETURN
Here's the first inserted state.
Again we'll wait until BIT_TIMER has reached 0 before we do anything.
Then we check to see if the input is really high, which it should be during this 2.5-bit time pause.
If it is not high we go into the error state, waiting for the input to get high before returning to state 0 again.
;---------STATE 3, EXPECTING START BIT, OR ANOTHER PAUSE IF BATTERY IS EMPTY--
IR_STATE_3 DECFSZ BIT_TIMER Wait until center of first half of
RETURN start bit.
BTFSS PORTA,4 Is it the start bit (if input is low)?
GOTO IR_START_BIT Yes! Handle it!
BSF FLAGS,7 Set battery empty flag
MOVLW HALF_TIME*2 Next stop is really the start bit!
MOVWF BIT_TIMER
MOVLW IR_STATE_4 Next time handle first half of a bit
MOVWF IR_STATE
RETURN
The second inserted state is where we expect the first data bit, but only if we have waited until we are in the centre of the bit.
If the IR input is low now we are indeed receiving the first bit, in which case we jump to IR_START_BIT which handles the rest.
;-----------------------------------IR STATE 4, WAIT FOR FIRST HALF OF A BIT--
IR_STATE_4 DECFSZ BIT_TIMER Wait until center of first half of bit
RETURN Keep waiting!
MOVLW IR_STATE_5 Next state is 5 if input is low
BTFSS PORTA,4
IR_START_BIT MOVLW IR_STATE_6 Input is high, next state is 6
MOVWF IR_STATE
MOVLW HALF_TIME Restart bit timer
MOVWF BIT_TIMER
RETURN
Nothing special in this state if you compare it to IR_STATE_2 of the RC-5 decoder software. The only difference is the presence of the label IR_START_BIT, which is the jump destination from state 3. ;---------------IR STATE 5, FIRST HALF WAS HIGH NOW IT MUST BE LOW FOR A "0"--
IR_STATE_5 DECFSZ BIT_TIMER Wait until center of 2nd half of bit
RETURN Keep waiting!
BTFSC PORTA,4 Is input high now?
GOTO .ERROR Nope! It's an error!
BCF STATUS,CARRY A 0 was received, shift it in result
RRF IR_SHIFT+1,F
RRF IR_SHIFT,F
MOVLW HALF_TIME Restart bit timer
MOVWF BIT_TIMER
MOVLW IR_STATE_4 In case we need some more bits
BTFSC STATUS,CARRY We're done when Carry is 1
MOVLW IR_STATE_7 Carry is 1, received entire message
MOVWF IR_STATE
RETURN
.ERROR MOVLW IR_ERROR_0 Wait until input gets high before
MOVWF IR_STATE returning to state 0
RETURN
Nothing special in this state compared to state 3 of the RC-5 decoding software. Oh, there is one thing: the polarity of the received bit which is inverted compared to RC-5.
Ehhh, how can this routine tell when a complete message is received?
With RC-5 we prepared the shift register with a special value, but with NRC-17 we only cleared the entire shift register.
;---------------IR STATE 6, FIRST HALF WAS LOW NOW IT MUST BE HIGH FOR A "1"--
IR_STATE_6 DECFSZ BIT_TIMER Wait until center of 2nd half of bit
RETURN Keep waiting!
BTFSS PORTA,4 Is input high now?
GOTO IR_ERROR_1 Nope! It's an error!
BSF STATUS,CARRY A 1 was received, shift it in result
RRF IR_SHIFT+1,F
RRF IR_SHIFT,F
MOVLW HALF_TIME Restart bit timer
MOVWF BIT_TIMER
MOVLW IR_STATE_4 In case we need some more bits
BTFSC STATUS,CARRY We're done when Carry is 1
MOVLW IR_STATE_7 Carry is 1, message complete!
MOVWF IR_STATE
RETURN
Again nothing special compared to state 4 of the RC-5 decoding software, only the polarity of the received bit is inverted. ;--------------------------IR STATE 7, MESSAGE RECEIVED, START PROCESSING IT--
IR_STATE_7 INCF IR_SHIFT+1,W Could it be address $FF, command $FE?
BTFSS STATUS,ZERO
GOTO .SKIP No, it can't be!
MOVLW 2
ADDWF IR_SHIFT,W
BTFSC STATUS,ZERO
GOTO .QUIT It is $FF, $FE. Don't display it
.SKIP MOVLW CLR_TIME Set display clear timer
MOVWF CLR_DELAY
MOVLW DP_TIME Flash receive LED
MOVWF DP_DELAY
SWAPF IR_SHIFT+1,W Work from left to right
CALL HEX2SEGMENTS
MOVWF DIGIT1
MOVF IR_SHIFT+1,W Do the same with 2nd digit
CALL HEX2SEGMENTS
ANDLW %0111.1111 Flash dot of this digit
MOVWF DIGIT2
SWAPF IR_SHIFT,W And with the 3d digit
CALL HEX2SEGMENTS
MOVWF DIGIT3
MOVF IR_SHIFT,W And finally with the last digit
CALL HEX2SEGMENTS
MOVWF DIGIT4
BTFSC FLAGS,7 Is battery empty?
BCF DIGIT4,7 Yes! Turn right most DP on
.QUIT MOVLW IR_STATE_8 Done enough for now. Let's finish it
MOVWF IR_STATE in the last state
RETURN
Once we arrive at IR_STATE_7 we received the entire message, which is now going to be decoded.
First of all we check whether the special start or stop code $FFFE was received, in which case we simply ignore it.
;----------------------------------IR STATE 8, WAIT FOR INPUT TO RETURN HIGH--
IR_STATE_8
IR_ERROR_0 MOVLW IR_STATE_0 Reset state machine only if input is
BTFSC PORTA,4 high
MOVWF IR_STATE
RETURN
;-----------------------------------------------------------IR ERROR STATE 1--
IR_ERROR_1 MOVLW IR_STATE_0 Return to IR state 0
MOVWF IR_STATE
RETURN
These two states should be familiar to you if you have seen the identical routines of the RC-5 decoder before. |