Z80 Software Delay - z80

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

If by 1.8MHz you mean exactly 1,800,000 Hz, then to get a 2 second delay you'd need to delay for 3,600,000 T-states. Your current delay loop takes 14 T-states per iteration, which means that your initial value for B would have to be 3600000/14 == 257143, which obviously won't fit in one byte.
The greatest number of iterations that you could specify with an 8-bit register is 256, and to reach 3,600,000 T-states with 256 iterations, each iteration would have to take 14,062 T-states. That's one big loop body.
If we use a 16-bit counter things start getting a bit more manageable. At 65,536 iterations we only need 55 T-states per iteration to reach a total of 3,600,000 T-states. Below is an example of what that could look like:
; Clobbers A, B and C
ld bc,#0
1$:
bit #0,a ; 8
bit #0,a ; 8
bit #0,a ; 8
and a,#255 ; 7
dec bc ; 6
ld a,c ; 4
or a,b ; 4
jp nz,1$ ; 10, total = 55 states/iteration
; 65536 iterations * 55 states = 3604480 states = 2.00248 seconds

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.

Related

difference between counting packets and counting the total number of bytes in the packets

I'm reading perfbook. In chapter5.2, the book give some example about statistical counters. These example can solve the network packet count problem.
Quick Quiz 5.2: Network-packet counting problem. Suppose that you need
to collect statistics on the number of networking packets (or total
number of bytes) transmitted and/or received. Packets might be
transmitted or received by any CPU on the system. Suppose further that
this large machine is capable of handling a million packets per
second, and that there is a system-monitoring package that reads out
the count every five seconds. How would you implement this statistical
counter?
There is one QuickQuiz ask about difference between counting packets and counting the total number of bytes in the packets.
I can't understand the answer. After reading it, I still don't know the difference.
The example in "To see this" paragraph, if changing number the 3 and 5 to 1, what difference does it make?
Please help me to understand it.
QuickQuiz5.26: What fundamental difference is there between counting
packets and counting the total number of bytes in the packets, given
that the packets vary in size?
Answer: When counting packets, the
counter is only incremented by the value one. On the other hand, when
counting bytes, the counter might be incremented by largish numbers.
Why does this matter? Because in the increment-by-one case, the value
returned will be exact in the sense that the counter must necessarily
have taken on that value at some point in time, even if it is
impossible to say precisely when that point occurred. In contrast,
when counting bytes, two different threads might return values that are
inconsistent with any global ordering of operations.
To see this, suppose that thread 0 adds the value three to its counter,
thread 1 adds the value five to its counter, and threads 2 and 3 sum the
counters. If the system is “weakly ordered” or if the compiler uses
aggressive optimizations, thread 2 might find the sum to be three and
thread 3 might find the sum to be five. The only possible global orders
of the sequence of values of the counter are 0,3,8 and 0,5,8, and
neither order is consistent with the results obtained.
If you missed > this one, you are not alone. Michael Scott used this
question to stump Paul E. McKenney during Paul’s Ph.D. defense.
I can be wrong but presume that idea behind that is the following: suppose there are 2 separate processes which collect their counters to be summed up for a total value. Now suppose that there are some sequences of events which occur simultaneously in both processes, for example a packet of size 10 comes to the first process and a packet of size 20 comes to the second at the same time and after some period of time a packet of size 30 comes to the first process at the same time when a packet of size 60 comes to the second process. So here is the the sequence of events:
Time point#1 Time point#2
Process1: 10 30
Process2: 20 60
Now let's build a vector of possible total counter states after the time point #1 and #2 for a weakly ordered system, considering the previous total value was 0:
Time point#1
0 + 10 (process 1 wins) = 10
0 + 20 (process 2 wins) = 20
0 + 10 + 20 = 30
Time point#2
10 + 30 = 40 (process 1 wins)
10 + 60 = 70 (process 2 wins)
20 + 30 = 50 (process 1 wins)
20 + 60 = 80 (process 2 wins)
30 + 30 = 60 (process 1 wins)
30 + 60 = 90 (process 2 wins)
30 + 90 = 110
Now presuming that there can be some period of time between time point#1 and time point#2 let's assess which values reflect the real state of the system. Apparently all states after time point#1 can be treated as valid as there was some precise moment in time when total received size was 10, 20 or 30 (we ignore the fact the the final value may not the actual one - at least it contains a value which was actual at some moment of system functioning). For the possible states after the Time point#2 the picture is slightly different. For example the system has never been in the states 40, 70, 50 and 80 but we are under the risk to get these values after the second collection.
Now let's take a look at the situation from the number of packets perspective. Our matrix of events is:
Time point#1 Time point#2
Process1: 1 1
Process2: 1 1
The possible total states:
Time point#1
0 + 1 (process 1 wins) = 1
0 + 1 (process 1 wins) = 1
0 + 1 + 1 = 2
Time point#2
1 + 1 (process 1 wins) = 2
1 + 1 (process 2 wins) = 2
2 + 1 (process 1 wins) = 3
2 + 1 (process 2 wins) = 3
2 + 2 = 4
In that case all possible values (1, 2, 3, 4) reflect a state in which the system definitely was at some point in time.

J interpretation of infinities

I have some difficulties understanding how J interprets infinities, for example (cos=.2&o.^:_)1 is 0.73908 and ((^&2)^:_) 2 is _, but ((+&1)^:_) 0 hung my computer instead of answering _. How does the cosine and power examples work ?
Your computer hangs because there are a lot (like A LOT) of steps until the last calculation reaches _.
If you keep the intermediate steps you can easily see how fast the cosine converges:
(2&o.^:(<_)) 1
1 0.540302 0.857553 0.65429 ...
#(2&o.^:(<_)) 1
77
In just 77 steps it reached a steady point.
Likewise, ^&2 increases very fast so it reaches its steady point (_) very soon:
((^&2)^:(<_)) 2
2 4 16 256 65536 4.29497e9 1.84467e19 3.40282e38 1.15792e77 1.34078e154 _
#((^&2)^:(<_)) 2
11
(+&1) on the other hand, is a very slowly increasing function. Starting from 0, you have to wait about 1e19 steps until it reaches a steady point; i.e. a number x that is tolerantly equal to x+1
The form v ^:_ y will apply v to y until there is no change. In other words it can be used as a convergence test.
((+&1)^:_) 0 NB. adds one each time that it executes... slowly reaches infinity
((^&2)^:_) 2 NB. increases much quicker so gets to _ (infinity) quicker
(cos=.2&o.^:_)1 NB. converges
In J for C programmers Henry Rich gives a good description of the uses of ^:_
http://www.jsoftware.com/help/jforc/loopless_code_iv_irregular_o.htm#_Toc191734389

Rounding off with zero at the end

We can round off a number say 23 or 74 to 20 and 70 by seeing the numbers lsb(right most bit) and 26 or 78 to 30 and 80.. My doubt is if this is possible in verilog codes... I want to know after converting into digital will this concept be possible..
In case you just want to make the LSB of any register zero you can always do something like this
reg [7:0] a;
reg [7:0] b = 23;
a = {b[7:1], 1'b0};
In general to round off integers of base n you add n/2 and the divide by n (discarding the remainder) and then multiply by n. So your examples above:
(23+5)/10 * 10 = 20
(28+5)/10 * 10 = 30
Doing this with binary logic is a bit expensive since you need to divide and multiply. However, if you are working with base 2 numbers then those operations are free since it is just a bit shift.
For an example in binary, let's say you want to round 61 to the nearest multiple of 8, which would be 64. In binary, 61 is 6'b011101. Add 8/2 (6'b000100) to this and you get 6'b100001 which is 65. Now divide by 8 and multiply by 8. Since that is just shift right by 3 and then shift left by three we can simply zero out the 3 lsbs to get 6'b100000 which is 64.

Bluetooth heartrate monitor byte decoding

Problem :
I am having trouble with understanding the returned data of the BLE Heart Rate Characteristic(service 180d, characteristic 2a37).
According to the specification there will be either 6 or 7 bytes of data (when base64-decoded), i fully understand how to deal with it when this is the case.
But sometimes it won't return 6 or 7 bytes but 8 and more rarely 4 bytes, i have no idea why there are more/less bytes and what the meaning of the added bytes is or which bytes are left out.
I could skip all the cases where there are not 6 or 7 bytes but i want to fully understand this.
I am certain that the converting the base64-encoded to byte-array is done correctly, i made a function for it and checked it using manual base64-decode combined with charCodeAt(index) and truly manually checked it using good ol' pencil, paper and brain (not necessarily in that order).
TL;DR :
BLE Heart Rate (180d,2a37) sometimes does not return the expected amount of bytes (4 and 8 when it should be either 6 or 7 bytes).
What exactly happened and why?
Example :
// Example results in byte-array's
["00010110", "01110111", "00000100", "00000010"] // unexpected 4 byte
["00010110", "01111000", "11111111", "00000001", "11111111", "00000001", "00001100", "00000001"] // unexpected 8 byte
["00010110", "01110111", "00001000", "00000010", "00001000", "00000010"] // normal 6 byte
// Example results in hex-array's (easier to read on small screens)
["0x16","0x77","0x04","0x02"] // unexpected 4 byte
["0x16","0x78","0xFF","0x01","0xFF","0x01","0x0C","0x01"] // unexpected 8 byte
["0x16","0x77","0x08","0x02","0x08","0x02"] // normal 6 byte
Byte Explanation :
Flags. The first bit (most right) is on if the heart rate is in 16 bit format (i only got 8 bit).
heartrate, if the heart rate is in 16 bit format there will be 2 bytes here
energy expended
energy expended
rr interval
rr interval
Energy expenditure is optional check the bit 3 of the flags in your sample data case it is not present. There are a variable number of rr intervals. with 4 bytes you have just 1 with 6 bytes you have 2 and with 8 bytes you have 3 you could in theory get 10 and 4.
You should decode the bytes using the flags then if rr's are present the number of bytes left / 2 is the number of rr's you have.
See the XML-Definition file for more details.

Is there a J idiom for adding to a list until a certain condition is met?

Imagine you're generating the Fibonacci numbers using the obvious, brute-force algorithm. If I know the number of Fibonaccis I want to generate in advance, I can do something like this using the power conjunction ^::
(, [: +/ _2&{.)^:20 i.2
How can I instead stop when the Fibonaccis reach some limit, say 1e6? (I know how to do this inside a function using while., but that's no fun.)
I want to stress that this is a general question about J, not a specific question about Fibonacci. Don't get too distracted by Fibonacci numbers. The heart of the question is how to keep appending to a list until some condition is met.
Power has also a verb form u^:v^:n where the second verb can be used as a check. Eg: double (+:) while (n is _) less than 100 (100&>):
+:^:(100&>)^:_ ] 1
128
+:^:(100&>)^:_ ] 3
192
As usual, to append to the result of power, you box the noun:
+:^:(100&>)^:(<_) ] 3
3 6 12 24 48 96 192
I think the best answer to this is in Henry Rich's book J for C programmers. Specifically, it using the Power Conjunction ^: . You can also use it to converge until there is no change, so that the limit would not need to be defined. Henry uses the example that:
2 *^:(100&>#:])^:_"0 (1 3 5 7 9 11)
128 192 160 112 144 176
The ^:_ Power Conjunction repeats until there is no change and the ^:(100&>#:]) tests for the result being less than 100. If it is then ^: is applied to 1 and the loop 2* is done again, if it is not less than 100 then ^: would be applied to 0 and that results in it doing nothing and nothing changes and the loop exits. The fact that it use "0 as the rank means that it can apply the doubling function 2* to each of 1 3 5 7 9 11 individually.
Henry really does explain the process better than I, so here is the reference for further reading.
http://www.jsoftware.com/help/jforc/loopless_code_iv_irregular_o.htm#_Toc191734389

Resources