Parity check - 18M parts

g6ejd

Senior Member
Has anyone figured out how to conduct a simple parity check with the 18M2 part. Easy with X2 parts becuase they have the NOB - Number Of Bits command.

I have my MSF receiver getting and displaying time, but I'm trying to stop it updating a DS1307 RTC when there are reception errors. If the on-board RTC time is different from received time, I want to update the on-board RTC (e.g. clock drift). To do that, I've applied basic checks and the only thing left to do is use the received parity bit, broadcast a number of seconds later with parity as ODD. e.g. Mins = $07 then parity bit = 0 if Mins = $06 then parity bit = 1

The task is to check received 'Mins' formated as BCD (XX,40,20,10,8,4,2,1) against a received parity bit, then if correct (parity = ODD) update the on-board RTC.

If the picaxe basic allowed access to an overflow bit after a shift << or >> it would make it easier. Attempts so-far have used a loop (8 times for each bit) and AND each bit, counting the result but it's cumbersome.

Any ideas?
 

inglewoodpete

Senior Member
The PICAXE does not have an overflow bit per se, however it can be done by juggling bytes in word variables. You are probably aware that the PICAXE word variables share 2 x byte variables. Eg w0 is b1 and b0 combined.

To test an overflow bit after a >>, put the byte in the upper byte register of a word, clear the lower byte reg, do the shift right and test the lower byte register for zero/non-zero.

To test an overflow bit after a <<, put the byte in the lower byte register of a word, clear the upper byte reg, do the shift left and test the upper byte register for zero/non-zero.
 

g6ejd

Senior Member
thanks to @inglewoodpete I have now got a parity checker, here's a first cut:

Code:
bit_count = 0 ' Note 0 (zero) is an EVEN number
test_byte = $0007 ' shown in 16-bit form to denote the use of a word variable (in this case w0)
rx_parity = $00

for i = 0 to 7
  test_byte = test_byte * 2
  if b1 <> 0 then
    bit_count = bit_count + 1
    b1 = 0  
  endif
next i
byte_parity = bit_count AND $01 + rx_parity ' Now add received parity bit, result should be odd i.e. b0.bit0 = 1

if byte_parity = 1 then
  serout 6, n2400, ("PASS")
else
  serout 6, n2400, ("FAIL")
endif
'Results
'if test_byte = $07 ' 3 bits are set, so ODD parity
'if rx_parity = $01 ' Received a '1' for the parity check
'Result is a FAIL, too many bits in test_byte are set or rx_parity bit was received incorrectly, should have been a 0, so probably an error
'Had the rx_parity been received as a '0' it would have passed
 

westaust55

Moderator
You could also achieve the same without the need for any word variables.
Untested but have a look at:
Code:
SYMBOL reserved  = b0 ; reserved for bit variables
SYMBOL   testbit = bit0 ; remember this is a part of byte variable b0
SYMBOL   byte_parity = bit1
SYMBOL test_byte = b4
SYMBOL pointer   = b5 
SYMBOL rx_parity = b6
SYMBOL bit_count = b7

rx_parity = $00
bit_count = $00 ' Note 0 (zero) is an EVEN number
test_byte = $07 ' 

	FOR pointer = 0 TO 7
		
		testbit = test_byte AND $01  ; even the AND $01 may not be required - putting a byte into a bit only the lsb is used
		IF testbit = 1 THEN
	  		INC bit_Count
		ENDIF
		test_byte = test_byte /2
	NEXT pointer

byte_parity = bit_count AND $01 + rx_parity ' Now add received parity bit, result should be odd i.e. b0.bit0 = 1

if byte_parity = 1 then
  serout 6, n2400, ("PASS")
else
  serout 6, n2400, ("FAIL")
endif
 

westaust55

Moderator
Maybe the brain has not kicked in fully yet, but for the lines

Code:
byte_parity = bit_count AND $01 + rx_parity ' Now add received parity bit, result should be odd i.e. b0.bit0 = 1

if byte_parity = 1 then
if the calculated parity = 1 and the received parity = 1 then byte_parity will be 2 if a byte variable or 0 if a bit variable
may be better as
Code:
byte_parity = bit_count AND $01 

if byte_parity = rx_parity then
or you may need to swap the "Pass" and "FAIL" text
 

hippy

Technical Support
Staff member
If 'test_byte' can be aliased to 'b0' then a parity test can be quickly calculated using the 'bit0' to 'bit7' values ...

b1 = bit0 ^ bit1 ^ bit2 ^ bit3 ^ bit4 ^ bit5 ^ bit6 ^ bit7

This is the equivalent of ...

b1 = NOB b0 & 1

Then all that needs to be checked is whether b1 holds a 0 or 1
 

g6ejd

Senior Member
@hippy thank you for your idea (b1 = bit0 ^ bit1 ^ bit2 ^ bit3 ^ bit4 ^ bit5 ^ bit6 ^ bit7).

I've tested it, it works perfectly, I've just added it to the code of my MSF Rx and I'm sat here watching it work as it should.

Respect...

Dave G6EJD
 

g6ejd

Senior Member
@westaust55
"if the calculated parity = 1 and the received parity = 1 then byte_parity will be 2 if a byte variable or 0 if a bit variable may be better as..."

The result is the received byte plus the received parity bit which together give an ODD parity result, so in my examples RxByte = 07 (3-bits) and I set the RxParity = 01 (1-bit) to force a fail as the result would be a total of 4-bits, if received correctly it should have been a RxParity = 00. I did not explain that too well in my example.
 

westaust55

Moderator
If 'test_byte' can be aliased to 'b0' then a parity test can be quickly calculated using the 'bit0' to 'bit7' values ...

b1 = bit0 ^ bit1 ^ bit2 ^ bit3 ^ bit4 ^ bit5 ^ bit6 ^ bit7

This is the equivalent of ...

b1 = NOB b0 & 1

Then all that needs to be checked is whether b1 holds a 0 or 1

Hippy,
It could be worth including that non-X2 workaround/equivalent in manual 2 adjacent to the NOB command.
Akin to the code examples for non X1 & X2 parts at the SHIFTOUT command.
 
Careful on relying only on the parity. I coded an MSF receiver too and have had a number of occasions where a double bit error has snuck through. Always compare the time for reasonableness (e.g. against the previous time + a minute) before using it.
 

g6ejd

Senior Member
Thanks, this is exactly what I'm doing, I only adjust the RTC if the time Rx is within a 5-min boundary and it passes the (new method of) parity check (i.e. ODD for MSF), that's as good as it gets. Without these tests it's forever setting time based on noisy signals. I might extend the time adjustment to once/day now I have it all runinng, currently it's every minute, or perhaps at a given time of the day like 0200Hrs
 
Top