Longitudinal Redundancy Check (LRC)

techElder

Well-known member
#1
Here's a snippet that I've used to generate a longitudinal redundancy check (LRC). I have used it on an RS-485 setup with success. It is fast and provides some minimum checking. I've forced 1-bit errors to show up, but haven't done any documented testing. The algorithm is straight from MODBUS when ASCII only is transmitted.

Code:
[color=Navy]#macro [/color][color=Black]LRC_RAM[/color][color=Blue]([/color][color=Purple]LRC[/color][color=Black],[/color][color=Blue]LRCRAM_BEG[/color][color=Black],[/color][color=Blue]LRCRAM_END) [/color][color=Green]; "2018-01-06 06:12:19"
   ' Procedure to generate longitudinal redundancy check (LRC) 8-bit field
   ' Uses bptr, LRC (byte variables)
   ' Uses LRCRAM_BEG, LRCRAM_END as constants pointing to start RAM and end RAM
   ' bptr is set to the beginning RAM location of bytes to be added
   ' All bytes important including LRCRAM_BEG to LRCRAM_END
   ' LRC is poked into the last byte; LRCRAM_END
   [/color][color=Purple]LRC [/color][color=DarkCyan]= [/color][color=Navy]0                                   [/color][color=Green]; clear sum
   [/color][color=Purple]bptr [/color][color=DarkCyan]= [/color][color=Blue]LRCRAM_BEG                         [/color][color=Green]; start here in RAM
   [/color][color=Blue]do
      [/color][color=Purple]LRC [/color][color=DarkCyan]= [/color][color=Purple]LRC [/color][color=DarkCyan]+ [/color][color=Purple]@bptrinc                   [/color][color=Green]; Add in 8-bit variable (carries discarded)
   [/color][color=Blue]loop until [/color][color=Purple]bptr [/color][color=DarkCyan]= [/color][color=Blue]LRCRAM_END              [/color][color=Green]; Changed from ">" ; "2018-01-06 06:12:36"
   'LRC = $FF - LRC                           ; Subtract from 0xFF to produce a ones-complement
   'LRC = LRC + 1                             ; Add 1 to produce the twos-complement
   'poke bptr, LRC                            ; Poke LRC into 1 byte after LRCRAM_END
   [/color][color=Purple]@bptr [/color][color=DarkCyan]= - [/color][color=Purple]LRC
   LRC [/color][color=DarkCyan]= [/color][color=Purple]@bptr                               [/color][color=Green]; Update and return the variable from RAM[/color]
[color=Navy]#endm[/color]
Originally, I posted this on an HC-12 thread and got some interesting additions from forum members.

lbenson - Why, at the end of the loop, is "LRC = $FF - LRC + 1" preferable to just LRC?
Buzby - Because in the receiver you just need to sum the data including the LRC, and check that the result is zero. It's a bit quicker and saves a variable.

AllyCat - BTW the last three lines of Tex's LRC macro can be replaced by simply: @bptr = - LRC to save 8 bytes.

PS. This post is just to document what I (and others) had posted within the forum about a year ago (2017-JAN-25).
 
Last edited:

techElder

Well-known member
#2
LRC Receiving Side

Code:
[color=Navy]#macro [/color][color=Black]LRC_RAM_RX[/color][color=Blue]([/color][color=Purple]LRC[/color][color=Black],[/color][color=Blue]LRCRAM_BEG[/color][color=Black],[/color][color=Blue]LRCRAM_END) [/color][color=Green]; "2018-01-06 06:12:26"
   ' Procedure to recalculate longitudinal redundancy check (LRC) 8-bit field
   ' Note that a correctly received packet from LRCRAM_BEG including LRCRAM_END will sum to zero.
   ' Uses bptr, LRC (byte variables)
   ' Uses LRCRAM_BEG, LRCRAM_END as constants pointing to start RAM and end RAM
   ' bptr is set to the beginning RAM location of bytes to be added
   ' Note that LRCRAM_END includes received LRC
   [/color][color=Purple]LRC [/color][color=DarkCyan]= [/color][color=Navy]0                                   [/color][color=Green]; clear sum
   [/color][color=Purple]bptr [/color][color=DarkCyan]= [/color][color=Blue]LRCRAM_BEG                         [/color][color=Green]; start here in RAM
   [/color][color=Blue]do
      [/color][color=Purple]LRC [/color][color=DarkCyan]= [/color][color=Purple]LRC [/color][color=DarkCyan]+ [/color][color=Purple]@bptrinc                   [/color][color=Green]; Add in 8-bit variable (carries discarded)
   [/color][color=Blue]loop until [/color][color=Purple]bptr [/color][color=DarkCyan]> [/color][color=Blue]LRCRAM_END
   [/color][color=Green]' LRC will be zero for a correctly received packet[/color]
[color=Navy]#endm[/color]
 
Last edited:

techElder

Well-known member
#3
LRC Example Code

Code:
[color=Green]' Produced by Texasclodhopper for PICAXE forum Code Snippets ; "2018-01-06 06:12:04"
' Sample code to simulate the use of a Longitudinal Redundancy Check algorithm
'  for testing a packet of data sent over a possibly noisy link between two systems
'  NOTE: This is not a CRC (which would be more robust in error indication)[/color]

[color=Blue]symbol [/color][color=Purple]LRC [/color][color=DarkCyan]= [/color][color=Purple]b0[/color]
[color=Blue]symbol LRCRAM_BEG [/color][color=DarkCyan]= [/color][color=Navy]28 [/color][color=Green]' LRC calculated starting here to RAM_END[/color]
[color=Blue]symbol LRCRAM_END [/color][color=DarkCyan]= [/color][color=Navy]41 [/color][color=Green]' LRC is last byte POKED into this address[/color]

[color=Navy]#macro [/color][color=Black]LRC_RAM[/color][color=Blue]([/color][color=Purple]LRC[/color][color=Black],[/color][color=Blue]LRCRAM_BEG[/color][color=Black],[/color][color=Blue]LRCRAM_END) [/color][color=Green]; "2018-01-06 06:12:19"
   ' Procedure to generate longitudinal redundancy check (LRC) 8-bit field
   ' Uses bptr, LRC (byte variables)
   ' Uses LRCRAM_BEG, LRCRAM_END as constants pointing to start RAM and end RAM
   ' bptr is set to the beginning RAM location of bytes to be added
   ' All bytes important including LRCRAM_BEG to LRCRAM_END
   ' LRC is poked into the last byte; LRCRAM_END
   [/color][color=Purple]LRC [/color][color=DarkCyan]= [/color][color=Navy]0                                   [/color][color=Green]; clear sum
   [/color][color=Purple]bptr [/color][color=DarkCyan]= [/color][color=Blue]LRCRAM_BEG                         [/color][color=Green]; start here in RAM
   [/color][color=Blue]do
      [/color][color=Purple]LRC [/color][color=DarkCyan]= [/color][color=Purple]LRC [/color][color=DarkCyan]+ [/color][color=Purple]@bptrinc                   [/color][color=Green]; Add in 8-bit variable (carries discarded)
   [/color][color=Blue]loop until [/color][color=Purple]bptr [/color][color=DarkCyan]= [/color][color=Blue]LRCRAM_END              [/color][color=Green]; Changed from ">" ; "2018-01-06 06:12:36"
   'LRC = $FF - LRC                           ; Subtract from 0xFF to produce a ones-complement
   'LRC = LRC + 1                             ; Add 1 to produce the twos-complement
   'poke bptr, LRC                            ; Poke LRC into 1 byte after LRCRAM_END
   [/color][color=Purple]@bptr [/color][color=DarkCyan]= - [/color][color=Purple]LRC
   LRC [/color][color=DarkCyan]= [/color][color=Purple]@bptr                               [/color][color=Green]; Update and return the variable from RAM[/color]
[color=Navy]#endm

#macro [/color][color=Black]LRC_RAM_RX[/color][color=Blue]([/color][color=Purple]LRC[/color][color=Black],[/color][color=Blue]LRCRAM_BEG[/color][color=Black],[/color][color=Blue]LRCRAM_END) [/color][color=Green]; "2018-01-06 06:12:26"
   ' Procedure to recalculate longitudinal redundancy check (LRC) 8-bit field
   ' Note that a correctly received packet from LRCRAM_BEG including LRCRAM_END will sum to zero.
   ' Uses bptr, LRC (byte variables)
   ' Uses LRCRAM_BEG, LRCRAM_END as constants pointing to start RAM and end RAM
   ' bptr is set to the beginning RAM location of bytes to be added
   ' Note that LRCRAM_END includes received LRC
   [/color][color=Purple]LRC [/color][color=DarkCyan]= [/color][color=Navy]0                                   [/color][color=Green]; clear sum
   [/color][color=Purple]bptr [/color][color=DarkCyan]= [/color][color=Blue]LRCRAM_BEG                         [/color][color=Green]; start here in RAM
   [/color][color=Blue]do
      [/color][color=Purple]LRC [/color][color=DarkCyan]= [/color][color=Purple]LRC [/color][color=DarkCyan]+ [/color][color=Purple]@bptrinc                   [/color][color=Green]; Add in 8-bit variable (carries discarded)
   [/color][color=Blue]loop until [/color][color=Purple]bptr [/color][color=DarkCyan]> [/color][color=Blue]LRCRAM_END
   [/color][color=Green]' LRC will be zero for a correctly received packet[/color]
[color=Navy]#endm[/color]

[color=Green]'=============================
'==== PROGRAM STARTS HERE ====
'=============================

' load some sample data into RAM[/color]

[color=Purple]bptr [/color][color=DarkCyan]= [/color][color=Blue]LRCRAM_BEG [/color][color=Green]' sample data[/color]
[color=Blue]poke [/color][color=Purple]bptr[/color][color=Black], [/color][color=Red]":"[/color][color=Black],[/color][color=Navy]3[/color][color=Black],[/color][color=Navy]1[/color][color=Black],[/color][color=Navy]0[/color][color=Black],[/color][color=Navy]0[/color][color=Black],[/color][color=Navy]0[/color][color=Black],[/color][color=Navy]0[/color][color=Black],[/color][color=Navy]0[/color][color=Black],[/color][color=Navy]0[/color][color=Black],[/color][color=Navy]0[/color][color=Black],[/color][color=Navy]0[/color][color=Black],[/color][color=Navy]0[/color][color=Black],[/color][color=Navy]0[/color][color=Black],[/color][color=Navy]0 [/color][color=Green]' 14 bytes
'           1  2 3 4 5 6 7 8 9 0 1 2 3 4
'           28 . . . . . . . . . . . 40.
'                                      ^
'                                      LRC -> RAM_END

'===========================
'==== TRANSMITTING SIDE ====
'===========================[/color]

[color=Blue]sertxd([/color][color=Red]"Calculating LRC ..."[/color][color=Black],[/color][color=Blue]cr[/color][color=Black],[/color][color=Blue]lf[/color][color=Black],[/color][color=Blue]cr[/color][color=Black],[/color][color=Blue]lf)    [/color][color=Green]; display start

' execute the LRC macro with the sample data loaded[/color]
[color=Black]LRC_RAM[/color][color=Blue]([/color][color=Purple]LRC[/color][color=Black],[/color][color=Blue]LRCRAM_BEG[/color][color=Black],[/color][color=Blue]LRCRAM_END)[/color]

[color=Green]' display (on terminal) what is stored in RAM[/color]
[color=Blue]sertxd([/color][color=Red]"Displaying RAM with LRC ..."[/color][color=Black],[/color][color=Blue]cr[/color][color=Black],[/color][color=Blue]lf[/color][color=Black],[/color][color=Blue]cr[/color][color=Black],[/color][color=Blue]lf)    [/color][color=Green]; display start[/color]

[color=Purple]bptr [/color][color=DarkCyan]= [/color][color=Blue]LRCRAM_BEG                            [/color][color=Green]; where ":" is located[/color]
[color=Blue]for [/color][color=Purple]bptr [/color][color=DarkCyan]= [/color][color=Blue]LRCRAM_BEG to LRCRAM_END
   sertxd([/color][color=Black]#[/color][color=Purple]@bptr[/color][color=Black],[/color][color=Red]" "[/color][color=Blue])
next
sertxd(cr[/color][color=Black],[/color][color=Blue]lf[/color][color=Black],[/color][color=Red]"LRC = "[/color][color=Black],#[/color][color=Purple]LRC[/color][color=Black],[/color][color=Blue]cr[/color][color=Black],[/color][color=Blue]lf[/color][color=Black],[/color][color=Blue]cr[/color][color=Black],[/color][color=Blue]lf)            [/color][color=Green]; LRC returned value


'=============================
'==== SIMULATE ERROR BITS ====
'=============================

'sertxd("Simulating data transmission error ...",cr,lf,cr,lf)    ; display error bits
'poke 32,1 : poke 35,5                        ; screw up ram bits as desired for testing


'========================
'==== RECEIVING SIDE ====
'========================[/color]

[color=Blue]sertxd([/color][color=Red]"Recalculating received LRC ..."[/color][color=Black],[/color][color=Blue]cr[/color][color=Black],[/color][color=Blue]lf[/color][color=Black],[/color][color=Blue]cr[/color][color=Black],[/color][color=Blue]lf)    [/color][color=Green]; display LRC

' execute the LRC receiving macro as if from receiving end[/color]
[color=Purple]bptr [/color][color=DarkCyan]= [/color][color=Blue]LRCRAM_BEG                            [/color][color=Green]; start here in RAM[/color]
[color=Purple]LRC [/color][color=DarkCyan]= [/color][color=Navy]0                                      [/color][color=Green]; clear sum[/color]

[color=Black]LRC_RAM_RX[/color][color=Blue]([/color][color=Purple]LRC[/color][color=Black],[/color][color=Blue]LRCRAM_BEG[/color][color=Black],[/color][color=Blue]LRCRAM_END)[/color]

[color=Green]' display (on terminal) what is returned from macro
'  LRC should be zero if bits add up correctly[/color]
[color=Blue]sertxd([/color][color=Red]"Received LRC = "[/color][color=Black],#[/color][color=Purple]LRC[/color][color=Black],[/color][color=Blue]cr[/color][color=Black],[/color][color=Blue]lf) [/color][color=Green]; LRC

' upon return test for a non-zero condition[/color]
[color=Blue]if [/color][color=Purple]LRC [/color][color=DarkCyan]<> [/color][color=Navy]0 [/color][color=Blue]then
   sertxd([/color][color=Red]"Problem With Received Data (LRC <> ZERO)"[/color][color=Black],[/color][color=Blue]cr[/color][color=Black],[/color][color=Blue]lf)
else
   sertxd([/color][color=Red]"Received Data is AOK (LRC = ZERO)"[/color][color=Black],[/color][color=Blue]cr[/color][color=Black],[/color][color=Blue]lf)
endif

end[/color]
 
Last edited:
Top