Casio Calculator Communications BCD and Checksum code check

Anobium

Senior Member
I am completing a project to use my old Casio graphics calculator as a datalogger and graphical display for a Picaxe project.

The Picaxe gathers the data and sends the data to the calculator. It all works very nicely - I have a rolling set of data points being captured and the data is being graphed dynamically.

I currently have a limit of the data transmitted between 0 and 255, though I think 0 to 65335 is very practical. I cannot get my head around the coding relative to a CRC check the Casio requires and the hanlding of WORD numbers in BCD format.

The code below is the code I writen to create the CRC but it also shows the limits of the BCD data handling (actually the limit is in theory 999 but my sensor only returns currently returns 0-255).

The checksum calculation is shown in the table below:

Data Spec.jpg

The CRC essentially can be resolved to the code I have defined in the test routine - this will only work for 0-999 numbers - I want to change the code to be 0-65535 but I am struggling to get my mind around handling BCD and summing the BCD numbers (or the decimal equivilent) - my will fail at above 999 as I am 'mucking around' with the BCD numbering scheme to get the results I want.

Code:
symbol valueout = w2

symbol majval = b20
symbol minval = b21
symbol units = b22
symbol tens= b23
symbol hundreds = b24
symbol vname = b26
symbol checksum = b27

for w1 = 1 to 999
	valueout = w1

	bintoascii valueout, hundreds, tens, units

	' maj
		majval = hundreds - $30
		majval = majval * 16
		minval = tens - $30
		majval = majval + minval
	'min
		minval = units - $30
		minval = minval * 16
		
	checksum = majval + minval + 12 
	
	checksum = NOT checksum
	
	checksum = checksum + 1
next
A typical set of data to be sent from the Pixace to the Casio is as follows - this is a hardcoded value to send 123456789. The data format is described in the table shown in the attachment.

Code:
	serout  2, T9600_16, ( $3A,$00,$01,$00,$01,$01,$23, $45, $67, $89, $00, $00, $00, $01, $09, $9b)
I have implemented a checksum sub routines, support 0-999 as follows using the code shown above. An example - of a value of 255, retuuns BCD values $25 and $50 with a checksum of $7F.

Code:
	gosub crc: 'this routine sets up checksum, majval and minval as BCD values
	serout  2, T9600_16, ( $3A,$00,$01,$00,$01,$00,$00, $00, $00, majval, minval, $00, $00, $01, $09, checksum)
Any thoughts on how I can make handling the BCD easier and then to expand the handling to 65535 (or WORDS).

Thank you,

Anobium
 
Last edited:

geoff07

Senior Member
I'm a bit confused as to the crc, as my understanding is that you are sending a 26 byte string containing two real numbers and a simple checksum, and not a crc (cyclic redundancy check - something a bit more complex than a check digit, which won't allow error correction, whereas a crc will))

I assume you are using only bytes 1-15 and 26, the rest being zero.

I would have expected you to step through the digit positions, generating a byte each time, rather than stepping through the possible values. I'm clearly missing something.

If the bytes 1-15 are meant to be BCD (not stated in the table) then I would cycle through the number, extracting each digit, coding it, and sending it.

There then is no difference in approach between an 8 bit or a 16 bit number. Apologies if I have got the wrong end of the stick.
 

westaust55

Moderator
I concur with geoff07.

The table attached to post 1 mentions the last byte as a "checksum" which is completely different to a crc.
byte 26 = 01 + NOT SUM((bytes 1 to 25) - $3A) ; $3A = 58(dec)
 

Anobium

Senior Member
@westaust55. Oh yes. I did the research and most roads led to the Nexusresearch website. I have the Picaxe code from Micheal Fenton. The code does work but all data/value transmissions are essentially hardcoded (he has a limited set of values that can be transmitted/received) and the checksum is precalculated. There is no handling of BCD. I got this code yesterday after I finished my efforts.

Interesting, that all of the Picaxe searching I did provided nothing except for Micheals good work.

@Geoff07. Your idea may work. 'extracting each digit, coding it, and sending it.' and then I can calculate the checksum.

@all.... I edited/corrected the posting to refer to Checksum NOT CRC. :)
 

Anobium

Senior Member
I did what Geoff recommended. Just extracted and calculated.....

Resulting code now caters for WORDS = 0 to 65535.

Code:
symbol valueout = w2



symbol vname = b18
symbol checksum = b19
symbol byteval2 = b20
symbol byteval1 = b21
symbol hnunitsval = b22
' 65 53 5

symbol units = b27
symbol tens= b26
symbol hundreds = b25
symbol thousands = b24
symbol tenthousands = b23

for w1 = 1 to $ffff
	
	valueout = w1
	
	setfreq m32
	bintoascii valueout, tenthousands, thousands, hundreds, tens, units
	
	


		byteval2 = tenthousands - $30
		byteval2 = byteval2 * 16	
	'

		' use hnunitsval as temp variable
		hnunitsval = thousands - $30
		byteval2 = byteval2 + hnunitsval
		
		
		byteval1 = hundreds - $30
		byteval1 = byteval1 * 16
 

		hnunitsval = tens - $30
		byteval1 = byteval1 + hnunitsval
				
	'least sig byte
		hnunitsval = units - $30
		hnunitsval = hnunitsval * 16
		
	checksum =  byteval2 + byteval1 + hnunitsval + 12 
	
	checksum = NOT checksum
	
	checksum = checksum + 1
	setfreq m16
next
My CASIO datalogger works! I have live bar graphing and line graphing. Offline stats analysis in the calcualator. I can also use the calculator to return single values upon request - and, I can download the last 255 readings to my PC for further analysis.

A sample graph from the datalogger.

DataLogger Graph 001.jpg

I will post the completed project asap.


Anobium
 

hippy

Technical Support
Staff member
serout 2, T9600_16, ( $3A,$00,$01,$00,$01,$00,$00, $00, $00, majval, minval, $00, $00, $01, $09, checksum)
What I don't understand is you are sending 16 bytes yet the table showing how to calculate checksum indicates 26 bytes should be sent.

I don't see how what you are sending, nor how the checksum is calculated, relates to one another.
 

westaust55

Moderator
What I don't understand is you are sending 16 bytes yet the table showing how to calculate checksum indicates 26 bytes should be sent.
If we go and read the website by Michael Fenton, I think Anobium has posted the wrong table.
26 bytes relates to the transfer of Complex Numbers.

16 bytes (as per the attached) relates to the transfer of simple real number data
 

Attachments

Anobium

Senior Member
If we go and read the website by Michael Fenton, I think Anobium has posted the wrong table.
26 bytes relates to the transfer of Complex Numbers.

16 bytes (as per the attached) relates to the transfer of simple real number data

Yes. You are correct. My cut and paste was incorrect - I am calculating the checksum for the 16 bytes packet.

Silly me. :)
 

Anobium

Senior Member
Final Code - this example outputs DS18B20 to Casio FX-9750G

This code sample ouputs the integer value of a DS18B20 to the Casio FX-9750G datalogger.



This Picaxe Code.
Code:
#rem


This model supports DS18B20.  The CASIO displays integer temp values.

The 'Timer override switch' will cease the timed delay and output the current temp immediately to the Casio.



                                    ÚÄÄÄÄÄÄÄÄ¿
                                5v  ³1     18³ 0v
                   (Program Port) > ³2     17³ c.0 > LED out (& Program Port)
                    Sensor In c.4 > ³3     16³ c.1 < TTL Serial from Casio
        Timer Override Switch c.3 > ³4     15³ c.2 > TTL Serial out to Casio
                                    ÀÄÄÄÄÄÄÄÄÙ


#endrem

#no_data


' Support for DS18B20
Symbol TReading = W0
    Symbol Whole = B3
    Symbol Fract = B4
    Symbol SignBit = B5
    Symbol Digg = B6
    Symbol TempC_100 = W4


symbol indata1 = b1
symbol indata2 = b2


symbol valueout = w6

symbol vname = b18
symbol checksum = b19

	' 65 53 5
symbol byteval2 = b20
symbol byteval1 = b21
symbol hnunitsval = b22


symbol units = b27
symbol tens= b26
symbol hundreds = b25
symbol thousands = b24
symbol tenthousands = b23

symbol ledport = c.0
symbol casioInport = c.1
symbol casioOutport = c.2
symbol overrideswitch = pin3
symbol adcport = c.4

setfreq m16
pause 4000
sertxd ("Run",13,10) 
valueout = time

main:

indata1 = $FF ; set up a non-valid value
serin casioInport, T9600_16, indata1 ; receive 1 byte



if indata1 =$15 then ; if a byte was received 
{	high ledport

	' Send inital response, Picaxe is here!
	serout casiooutport, T9600_16, ( $13 )
	
	'Await for the Request Packet and obtain Variable name
	serin casioInport, T9600_16, ("REQ"), indata1;
	serin casioInport, T9600_16, ("VM"), indata1
	
	' the 12th byte has the variable name		
	serin [4000, fin1],casioInport, T9600_16, indata1,indata2,vname

	
	' pause to consume the bytes sent by Casio
	pause 250
	' Send Picaxe response to Request Packet
	serout  casiooutport, T9600_16, ( $06 )
	' sertxd ("Casio Variable: ", vname ,13,10)
	


	
	
	' Casio responds with $06 - consume byte, but do nothing
	serin casioInport, T9600_16, indata1

	if indata1 <> $06 then 
			sertxd ("Casio Error #1 code: ", #indata1,13,10)
	end if


	' Change the checksum from baseline of variable of A.  Easier than recalculating checksum
	'	checksum = $D0 equate to variable A
	
	checksum = $d0 - vname + 65
	' Send Variable description packet
	serout  casiooutport, T9600_16, ( $3a, $56, $41, $4c, $00, $56, $4d, $00, $01, $00, $01, vname, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $56, $61, $72, $69, $61, $62, $6c, $65, $52, $0a, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff, checksum )
	
	
	' Casio responds with $06 - consume byte, but do nothing
	serin casioInport, T9600_16, indata1
	
	if indata1 <> $06 then 
			sertxd ("Casio Error #2 code: ", #indata1,13,10)
	end if
	
	

	
	' read a value
	readtemp12 4,TReading: gosub CalcT
	gosub calcchecksum
	serout  casiooutport, T9600_16, ( $3A,$00,$01,$00,$01,$00,$00, $00, byteval2, byteval1, hnunitsval, $00, $00, $01, $09, checksum)
	
	' Casio responds with $06 - consume byte, but do nothing
	serin casioInport, T9600_16, indata1
	if indata1 <> $06 then 
			sertxd ("Casio Error #3 code: ", #indata1,13,10)
	end if
	
	
	' pause for 1 min
	' You must delay here or the Casio will time out!
	
	for b1 = 1 to 4 ‘ 4 loops
		for b0 = 1 to 240
			pause 250 ‘ wait 15 seconds
			if overrideswitch is on then sendendpacket
			toggle ledport
		next
	next b1
	
	
	sendendpacket:
	' Send end packet
		serout  casiooutport, T9600_16, ( $3A, $45, $4E, $44)
		for b0 = 5 to 49
				serout  casiooutport, T9600_16, ( $FF)
		next
		serout  casiooutport, T9600_16, ( $56)

	goto fin2
	fin1:
	sertxd ("Error",13,10) ; echo it back out
	fin2:
	low ledport
}
end if

low ledport




goto main



calcchecksum:
	setfreq m32
	bintoascii valueout, tenthousands, thousands, hundreds, tens, units
	
	
		byteval2 = tenthousands - $30
		byteval2 = byteval2 * 16	
	'

		' use hnunitsval as temp variable
		hnunitsval = thousands - $30
		byteval2 = byteval2 + hnunitsval
		
		
		byteval1 = hundreds - $30
		byteval1 = byteval1 * 16
 

		hnunitsval = tens - $30
		byteval1 = byteval1 + hnunitsval
				
	'least sig byte
		hnunitsval = units - $30
		hnunitsval = hnunitsval * 16
		
	checksum =  byteval2 + byteval1 + hnunitsval + 12 
	
	checksum = NOT checksum
	
	checksum = checksum + 1
	setfreq m16
return


CalcT:
		
       SignBit = Bit15
       If SignBit = 0 Then Positive
       ' its negative
       TReading = TReading ^ $ffff + 1 ' take twos comp

Positive:

      TempC_100 =  TReading * 6		' TC = value * 0.0625
      TReading = TReading * 25 / 100
      TempC_100 = TempC_100 + TReading


	valueout = TempC_100 / 100 

Return
 

SGraham

New Member
Hi All, I am trying to get my head round series communication with a checksum, like the program above. I thought I had understood the earlier versions of this program, but this one with no comments leaves me wondering. No mention of what PICAXE he is using but with a lot of them to use "serout at T9600" you needed to up the clock to 32 MHz "setfreq m32". this program uses this command in the Sub "calcchecksum" and the "setfreq m16" on exit. The "serout at T9600" is outside this Sub, and is done at 16 MHz. Earlier versions had this right. Does this code work?
 

hippy

Technical Support
Staff member
Hi All, I am trying to get my head round series communication with a checksum, like the program above. I thought I had understood the earlier versions of this program, but this one with no comments leaves me wondering. No mention of what PICAXE he is using
From the diagram at the head of the program it looks like it is an 8-pin PICAXE, probably an 08M2.

but with a lot of them to use "serout at T9600" you needed to up the clock to 32 MHz "setfreq m32".
I think that 9600 not being available at default 4MHz (M2) or 8MHz (X2) speeds, and that it is usually better to do higher baud rate communications at 32MHz, has led to suggesting using 32MHz but 16MHz can also work.

The SETFREQ before the "main:" label is reached will set 16MHz operation so any T9600_16 will be correct from then on.

this program uses this command in the Sub "calcchecksum" and the "setfreq m16" on exit. The "serout at T9600" is outside this Sub, and is done at 16 MHz. Earlier versions had this right. Does this code work?
At the start of the routine there is a SETFREQ M32, presumably so the routine, which only does calculations not any SEROUT or SERIN, runs as fast as possible. It then drops the speed back to 16MHz when done so the T9600_16 baud rates elsewhere actually give 9600 baud.
 

hippy

Technical Support
Staff member
Or the top end of an 18pin device, look at the numbers on the right.
The numbering would suggest 18-pin, but the power connections and pin naming does not match that -
Code:
           08M2                        18M2
         .--__--.                    .--__--.
     V+ -|      |- 0V           C.2 -|      |- C.1
 SI/C.5 -|      |- C.0/SO    SO/C.3 -|      |- C.0
    C.4 -|      |- c.1       SI/C.4 -|      |- C.7
    C.3 -|      |- C.2          C.5 -|      |- C.6
         `------'
 

Buzby

Senior Member
A bit odd that, but I suppose either will do the job, as long as the user wires according to the PICAXE datasheet !.
 

SGraham

New Member
Thank you both for helping me out with this. I now see that there is a thread that covers PICAXE DF Player interface. I will continue with my questions there. Thanks.
SGraham.
 
Top