Misc

A list of small routines that can help you. Feel free to add your own.

Battery Status

Directly polls the hardware for battery status. Thanks to Steve Riekeberg.

;Name: BatteryStatus
;Description: Returns if the batteries are good, or low and need changing.
;Inputs: None
;Outputs: Non-Zero = Good Batteries
         Zero = Batteries Low
;Destroys: A

GetBatteryStatus:
   in a, (2)
   and 01h
   ret

Boundary Check

Checks if coordinates is inside a designated box. Thanks to Adm. Wiggin.

; Your box coords (will not work with 0, keep x1 < x2, and y1 < y2 [duh])
#define x1 10
#define y1 10
#define x2 20
#define y2 30

check:
; a = x
; b = y
; returns c flag set if good
; returns c flag reset if no good (nc)
;  destorys af (quite obvious if one knows any z80 at all)
  cp x1
  jr c,nogood
  cp x2+1
  jr nc,nogood
  ld a,b
  cp y1
  jr c,nogood
  cp y2+1
  jr nc,nogood
;if it gets here, it's in the box!   Yay!  Hooray!  Peoples rejoice!
; as a side effect of the last operation, the carry flag is already set.
  ret
nogood:
  or a;to reset the carry flag
  ret

Center Text

Displays a string centered on the screen (small font). Thanks to WikiGuru.

;input:hl points to string
;output: string displayed centered on screen
;destroyed: all registers
;other remarks: (penrow) must be set before calling this sub-routine
;               first byte of string must be the length of the string

centertxt:
bcall(_SStringLength)
ld a,96        ;width of screen
sub b          ;subtract width of string
rra             ;divide by 2 to be centered
ld (pencol),a
ld b,(hl)
inc hl
bcall(_VPutSN)
ret

;to call:

...
ld hl,0
ld (penrow),hl
ld hl,txtTest
call centertxt
...

txtTest:
.db 11,"Sample Text"

Direct Input

Used for direct input. See here to learn more about direct input. Thanks to Steve Riekeberg.

;Name: DirectInput
;Inputs: A = Key Group
;Outputs: A = Key Code; Zero If None
;Destroys: A, B

DirectInput:
   ld b,a
   ld a,$ff ;Reset the keypad
   out (1),a
   ld a,b
   out (1),a
   in a,(1)
   ret

Hotspot

Checks if h>b, l>c, h<d, and l<e. Thanks to kermmartian and DarkerLine.

;----------Hot spot detection-----------
;inputs: b,c (first x and y cor)
;        d,e (last x and y cor)
;        h,l (current x,y)
;output: "c" flag [either true (set) or false (reset)]

hdetect:
 ld a,h
 cp b
 ccf
 ret nc
 cp d
 ret nc
 ld a,l
 cp c
 ccf
 ret nc
 cp e
 ret

On/Off Calc

Turns the calculator "off" and waits for user to press on. Note: Pulling batteries out will result in Ram Clear. Thanks to Taricorp.

;no inputs
    ld a,02h
    out (10h),a        ;Turn off LCD
    ld a,08h
    out (3),a
    call LCD_Delay
    ld a,36h
    out (4),a
    ld a,01h
    out (3),a
    halt        ;It halts until ON is pressed
    ld a,0Bh
    out (3),a
    ld a,03h
    out (10h),a            ;Turn the LCD back on
    res onKey,(iy+keyFlags)

Find Next App

This routine is useful if you want to manually search through the installed apps on a calculator.

FindNextApp:
;Inputs:
;     B is the base page of the app.
;Outputs:
;     c flag set if the field was found
;     nc means the app header subfield was not found
;     B is the number of pages of the app
;     A is the page of the next app
;     H is the input page number
;     L is the page number of the currently swapped in page in bank 1
;
;Comments:
;     This code must run in RAM
     in a,(6)
     ld c,a
     push bc     ;b is the app page, c is the current page
     ld a,b
     out (6),a
     call FindNumPages
     pop hl       ;h is the app page, l is the current page
     ld b,a
     ld a,l
     out (6),a
     ld a,h
     ret nc
     sub b
     scf
     ret
FindNumPages:
;Outputs:
;     c flag set if the field was found
;     nc means the app header subfield was not found
;     A is the number of app pages
;     B is 0
;     (HL) is the number of app pages
     ld hl,4000h
     ld bc,128
     ld a,c
     or a
FNPLoop:
     cpir
     ret po
     ret nz
     inc a
     cp (hl)
     jr z,$+6
     dec a
     jp FNPLoop
     inc l
     ld a,(hl)
     scf
     ret

IncHLMem1

When reading through data in MemBank1, this routine is particularly useful as it adjusts the flash pages accordingly, as well as the pointer HL. If HL does not point to data in MemBank1 (4000h~7FFFh) then HL will simply be incremented, which is useful if the data might be in RAM or flash.

IncHLMem1:
     inc l         ;    4    4*16384        65536
     ret nz        ;11| 5    64*5+16320*11  179840
     inc h         ;    4    4*64           256
     ret po        ;11| 5    11*63+5        698
     ld h,a
     in a,(6)      ;   11    11             11
     inc a         ;    4    4              4
     out (6),a     ;   11    11             11
     ld a,h
     ld h,40h      ;    7    7              7
     ret           ;   10    10

It destroys no registers and is very efficient. However, if you are really in need of speed, such as with a ReadArc routine, you can try something like this (conditionally calling the routine):
     inc l
     call z,IncMem1Ptr
     <<rest of code>>

IncMem1ptr
     inc h         ;    4    4*64           256
     ret po        ;11| 5    11*63+5        698
     ld h,a
     in a,(6)      ;   11    11             11
     inc a         ;    4    4              4
     out (6),a     ;   11    11             11
     ld a,h
     ld h,40h      ;    7    7              7
     ret           ;   10    10

SortA

This code is not as efficient as it could be, but it works. it sorts a bunch of bytes to be in ascending order:

SortA:
;Inputs:
;     BC is the size
;     HL is where the data is located
;Takes at least n iterations, at most n(n+1)/2
     ld d,h
     ld e,l
SortALoop:
     push bc
     push de
     ld a,(hl)
     call SwapBytes
SortLoop1:
     jp po,NextSort
     cp (hl)
     cpi
     jr c,SortLoop1
     dec hl
     call z,SwapBytes
     jr c,SortLoop1
EndSwap:
     pop de
     jr SortALoop+1
NextSort:
     pop hl
     pop bc
     dec hl
     add hl,bc
     or a
     sbc hl,de
     ret c
     ret z
     ld b,h
     ld c,l
     inc bc
     ex de,hl
     jp SortA+1
SwapBytes:
     inc bc
     push af
     ld a,(de)
     ldi
     dec hl
     ld (hl),a
     inc hl
     pop af
     scf
     ret

Set15MHz

This routine will set the calculator to 15MHz mode if possible:

Set15MHz:
;Ouputs:
;     Sets the calculator to 15MHz if possible
;     z flag set if the calc is at 6MHz, nz if at 15MHz
     in a,(2)
     rlca
     and 1
     out (20h),a
     ret

Set6MHz

This is pretty tiny (3 bytes) so it isn't worth making it a subroutine. In other words, just use it inline:

     xor a
     out (20h),a
Unless otherwise stated, the content of this page is licensed under GNU Free Documentation License.