I am a newbie here, so maybe this was discussed before.
I have this code that does 16bit math.
Running with some local patches to the IDE it seems to work.
; Simple thermostat with Anticipator cycler
; The control loop uses scaled 16 bit math
; The scale point is between the msb and lsb
;
; Psuedo code for the control
; antHeat is 4
; relayState 0 or 1
; The anticipator cycler is a first order lag function.
; It converts the switch differential in to a proportional
; controller based on the proportional Perr.
; With a switch differential of 1F, and antHeat of 4F
; the propotional band is 4F - 1F = 3F
;
; while (1)
; {
; sense = getTemperature();
; Perr = setpt - sense
; ant += (antHeat * relayState - ant) >> 32
; Cerr = Perr - ant
; if (Cerr > 0)
; relayState = 1;
; else if (Cerr <= -1)
; relayState = 0;
; delay(cycleTime)
; }
;
; Hardware:
;
; The Temperature is provided in msb, lsb form from an external circuit
; to the INPUT of the KENBAK-1. It is enabled by an external switch.
; b0 of the OUTPUT register selects: 1 = msb, 0 = lsb
;
; The control relay is connected to b2 of the OUTPUT
; antHeat is orged OUTPUT
; Anticipator heat is 4 degrees.
; This provides a short cut to antHeat * relayState:
; OUTPUT or antHeat*relaState is 4 when relay is on, 0 when off
;
; Application data
org 115
cycDly 1 ; 1 for debug
cycDlyh 0 ; 0 about 8ms per count
setpt 0
setpth 75
sense db
senseh db
Perr db
Perrh db
ant db
anth db
Cerr db
Cerrh db
loopCnt db ; Adjust org so this address is 127
org 128
antHeat db ; antHeat is b2 of OUTPUT
; Application program start
reset org 4 ; begining of program ram
control
; get the current temperature reading from INPUT
set 0,1,OUTPUT ; the input will now be the msb of the sensor
nop ; time to settle
;load B,INPUT
load B,73 ; debug at 73.5
set 0,0,OUTPUT ; the input will now be the lsb of the sensor
nop ; time to settle
;load A,INPUT
load A,128 ; debug at 73.5
; can optimize later to use neg16b and just add setpt
load X,#sense ; point to sense
jmk store16b ; Save sensor reading for debug
; calc Perr = setpt - sense
load X,#setpt ; point to spl
jmk load16b
load X,#sense ; point to sensl
jmk sub16b ; Perr = setpt - sense
load X,#Perr ; point to Perr
jmk store16b ; save Perr
; update the anticipator cycler
; anticipator ant = ant + (HVAC - ant) / 32
load A,0 ; antHeat low is always 0
load B,antHeat ; BA = antHeat, note output all other OUTPUT pins assumed to be 0
load X,#ant ; point to ant
jmk sub16b ; (antHeat - ant)
load X,5 ; shift 5 to divide by 32
jmk shr16b ; (antHeat - ant) >> 5
load X,#ant ; point to ant
jmk add16b ; ant += (antHeat - ant) >> 5
jmk store16b ; X still points to ant
; calculate the composite err
; cmperr = Perr - ant
jmk neg16b ; negate anticipator value in BA
load X,#Perr ; point to Perr
jmk add16b ; Cerr = Perr - ant
load X,#Cerr ; point to Cerr
jmk store16b ; store Cerr
; Update the relay state based on composite err
; if Cerr < 0 HVAC = 4 else if Cerr >= 1 HVAC = 0
jmp B,LT,chkOff ; Cerr > 0
rlyon set 2,1,OUTPUT ; Cerr > 0 so bit 2 relay output on
jmp cycleDelay
chkoff
load X,#S_ONE ; point to const scaled one
jmk add16b ; Cerr + 1, if still positive then cerr >-1
jmp B,LT,rlyOff ; Cerr <= -1
jmp cycleDelay
rlyOff set 2,0,OUTPUT ; Cerr <= -1 so bit 2 relay output off
; anticiaptor time constant simulated here
cycleDelay
load A,cycDly ;delay constant for anticipator cycler
load B,cycDlyh ;delay constant for anticipator cycler
load X,#ONE ;point to constant onel = 0x0001
delay jmk sub16b
jmp A,NE,delay
jmp B,NE,delay
load A,loopCnt
add A,1
store A,loopCnt
jmp control
; -------------------- End Appplication ----------------------------------
; -------------------- 16 bit math routines ------------------------------
;
; The math routines are in upper half of RAM
org 0
lsb db ; used for 16bit math indexing
msb db ; used for 16bit math indexing
org 133 ;Skip over the registers
; 16 bit load, store, saveTmp
; on entry X points to value to load
; return msb = B, lsb = A
load16b db
load A,lsb+X
load B,msb+X
jmp (load16b)
store16b db
store A,lsb+X
store B,msb+X
jmp (store16b)
saveTmp db
store A,TMP16
store B,TMP16h
jmp (saveTmp)
; 16 bit math routines
; on entry
; B is msb A is lsb if first operand
; X is the address of the second operand
;
; result msb = B lsb = A
; X is unchanged
; add16b
; sub16b
; neg16b
;
add16b db ; return address
add A,lsb+X
skp 1,0,OCA ; skip if no carry
add B,1 ; adjust for carry
add B,msb+X
jmp (add16b) ; return
sub16b db ; return address
sub A,lsb+X
skp 1,0,OCA ; skip if no carry
sub B,1 ; adjust for carry
sub B,msb+X
jmp (sub16b) ; return
neg16b db
store X,TMPX ; save X
load X,#TMPN16 ; point to tmp
jmk store16b
load A,0 ; load 0 to BA
load B,0
jmk sub16b ; subtract input from 0
load X,TMPX ; restore X
jmp (neg16b) ; return
; 16 bit div 2^n
; call with B = msb, A = lsb, X = places
; return B = msb, A = lsb, X = 0
shr16b db
sloop sft A,R,1 ; shift right lsb
set 7,0,A ; clear lsb b7
skp 0,0,B ; test b0 msb, skip it 0
set 7,1,A ; b0 lsb was 1 so set b7 lsb
sft B,R,1 ; shift right msb, if negative sign extend
sub X,1 ; dec place count
jmp X,NE,sloop ; if not done again
jmp (shr16b) ; return to caller
;Math system variables and constants
org 246
ZERO 0 ; math constant zero 0x0000
S_ONE 0 ; math constant scaled one low 0x0100
ONE 1 ;
ONEH 0 ; math constant one 0x0001
TMP16 db ; temporary 16b value
TMP16h db ;
TMPN16 db ; temp for neg16b
TMPN16h db ;
TMPX db ; place to save X
RAM_END db ; If adding data items make sure this address is < 256
Raw octal dump:
The IDE assembler is consistent with itself
Not sure if it matches nanoKENBAK-1
000 000 000 004 102 200 200 123 111 002 200 200 023 200 223 167
367 214 223 165 367 205 223 167 367 245 223 171 367 214 023 000
124 200 223 173 367 245 223 005 367 301 223 173 367 232 367 214
367 260 223 171 367 232 223 175 367 214 145 100 122 200 347 112
223 367 367 232 145 110 347 112 022 200 024 163 124 164 223 370
367 245 043 120 143 120 024 177 003 001 034 177 347 004 000 000
000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
000 000 000 001 000 000 113 000 000 000 000 000 000 000 000 000
000 000 000 000 000 000 026 000 126 001 357 205 000 036 000 136
001 357 214 000 034 372 134 373 357 223 000 006 000 212 201 103
001 106 001 357 232 000 016 000 212 201 113 001 116 001 357 245
000 234 376 223 374 367 214 023 000 123 000 367 245 224 376 357
260 000 011 072 000 202 001 172 000 051 213 001 243 302 357 301
000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
000 000 000 000 000 000 000 000 001 000 000 000 000 000 000 000