procedure delay_1us( byte in x ) is
if target_cpu == sx_12 then
pragma keep page, bank
-- cycles for argument passing, call and return
const call_overhead = 14
if target_clock > 10_000_000 then
const once_through = 16
const overhead =
( ( ( call_overhead + once_through ) * 1_000_000 ) / target_clock )
const one_us_cycles = target_clock / 1_000_000
const outer_loop_overhead = 12
const inner_loops =
( one_us_cycles - outer_loop_overhead - 6 ) / 4
var byte outer_counter, inner_counter
const byte yy = - ( overhead + 1 )
const byte zz = inner_loops + 1
assembler
local outer_loop, inner_loop
-- get argument, substitute zero if too small
movlw yy
bank addwf x, w
skpc
movlw 0
-- make local copy
bank movwf outer_counter
incf outer_counter, f
-- outer loop must take 1uS
outer_loop:
-- inner loop takes 6 + 4 * n
movlw zz
bank movwf inner_counter
page inner_loop
inner_loop:
decfsz inner_counter, f
goto inner_loop
-- outer loop again?
page outer_loop
bank decfsz outer_counter, f
goto outer_loop
end assembler
elsif target_clock == 10_000_000 then
const overhead_us = ( call_overhead + 16 ) / 10
var byte counter
const byte abc = - overhead_us
assembler
local loop, next
-- get argument, correct for overhead, minimum is zero
movlw abc
bank addwf x, w
skpc
movlw 0
-- loop, total cycles in assembler block is 16 + 10 * n
bank movwf counter
incf counter, f
loop:
nop
page goto next
next:
page loop
decfsz counter, f
goto loop
end assembler
elsif target_clock == 4_000_000 then
const overhead_us = ( call_overhead + 11 ) / 4
var byte counter
var byte xyz = - overhead_us
assembler
local loop
-- get argument, correct for overhead, minimum is zero
movlw xyz
bank addwf x, w
skpc
movlw 0
-- loop, total cycles in assembler block is 11 + 4 * n
bank movwf counter
incf counter, f
page loop
loop:
decfsz counter, f
goto loop
end assembler
else
pragma error -- clock must be 4 or >=10 MHz
end if
elsif ( target_cpu == pic_14 ) | ( target_cpu == pic_12 ) then
const ips = target_clock / 4
if target_clock >= 10_000_000 then
const i_iteration = 5
const i_overhead = 9
const d_iteration = ( i_iteration * 1_000_000 ) / ips
const d_overhead = ( i_overhead * 1_000_000 ) / ips
const x_iteration = - d_iteration
const x_overhead = - ( d_overhead + ( d_iteration / 2 ) + 1 )
var byte v_overhead = x_overhead
var byte v_iteration = x_iteration
assembler
local loop
page loop
movfw x
addwf v_overhead, w
loop:
skpc
retlw 0
addwf v_iteration, w
goto loop
end assembler
elsif target_clock == 4_000_000 then
const i_iteration = 4
const i_overhead = 9
const d_iteration = ( i_iteration * 1_000_000 ) / ips
const d_overhead = ( i_overhead * 1_000_000 ) / ips
const x_iteration = - d_iteration
const x_overhead = - ( d_overhead + ( d_iteration / 2 ) + 1 )
var byte v_overhead = x_overhead
var byte v_iteration = x_iteration
assembler
local loop
page loop
movfw x
addwf v_overhead, w
skpc
retlw 0
loop:
addwf v_iteration, w
skpnc
goto loop
end assembler
else
pragma error -- clock must be 4 or 10 MHz
end if
else
pragma error -- cpu must be sx_12 or pic_14
end if
end procedure