'Z80 Software Delay

I am trying to create a software delay. Here is a sample program of what I am doing:

    Address  Data   Opcode  Comment    
    1800      06    LD, B   Load register B with fix value
    1801      “ “           Fixed value
    1802      05    DEC, B  Decrement value in register B
    1803      C2    JP cc   Jump to 1802 if value is not 0
    1804      02    -       Address XX
    1805      18    -       Address XX

My question is how can I calculate the required fixed value to load into register B so that the process of decrementing the value until 0 takes 2 seconds?

In my manual the time given to run the instructions is based on a 4MHz CPU but the Z80 CPU I am using has a speed of 1.8MHz. Any idea how I can calculate this? Thanks. P.S here is the decrement (DEC) and jump (JP cc) instructions from the manual:

Instruction    M Cycles    T states   4 MHz E.t
DEC r             1           4         1.00
JP cc             3       10 (4,3,3)    2.50
z80


Solution 1:[1]

I'm a bit of an optimization freak, so here is my go using the syntax with which I am most familiar (from the TASM assembler and similar):

Instruction   opcode    timing
ld bc,$EE9D   ;01EE9D   10cc
ex (sp),hl    ;E3       19*(256C+B)
ex (sp),hl    ;E3       19*(256C+B)
ex (sp),hl    ;E3       19*(256C+B)
ex (sp),hl    ;E3       19*(256C+B)
djnz $-4      ;10FA     13cc*(256C+B) - 5*C
dec c         ;0D       4*C
jr nz,$-7     ;20F7     12*C-5

This code is 12 bytes and 3600002 clock cycles.

EDIT: It seems like part of my answer is gone! To answer your question better, your Z80 can process 1800000 clock cycles in one second, so you need twice that (3600000). If you add up the timings given in my code, you get:

=10+(256C+B)(19*4+13)-5C+4C+12C-5

=5+(256C+B)89+11C

=5+22795C+89B

So the code timing is largely dependent on C. 3600000/22795 is about 157, so we initialize C with 157 (0x9D). Plugging this back in, we get B to be roughly 237.9775, so we round that up to 238 (0xEE). Plugging these in gets our final timing of 3600002cc or roughly 2.000001 seconds. This assumes that the processor is running at exactly 1.8MHz which is very unlikely.

As well, if you can use interrupts, figure out roughly how many times it fires per second and use a loop like halt \ djnz $-1 . This saves a lot more in terms of power consumption.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1