What does IM0/1 mean in z80.info decoding? - simulator

I am in the process of writing (yet another) Z80 simulator.
I am using the decoding page on the z80.info site.
In the section with the lookup/disssambly tables it says that for index 1 and 5 the Interrupt Mode is IM0/1. This table is referred to from the IM instruction (ED) X=1, Z=6.
What does IM0/1 mean exactly?
I know it's not an official instruction but I am also trying to support undocumented instructions.

As found here, quoting from Gerton Lunter:
The instructions ED 4E and ED 6E are IM 0 equivalents: when FF was put on the bus
(physically) at interrupt time, the Spectrum continued to execute normally, whereas
when an EF (RST 28h) was put on the bus it crashed, just as it does in that case when
the Z80 is in the official interrupt mode 0. In IM 1 the Z80 just executes a RST 38h
(opcode FF) no matter what is on the bus.
So it pretty much means IM 0, and I'm not sure where the commonly seen /1 comes from.

IM0/1/2 are instructions setting the Z80 CPU int interrupt mode 0/1/2. Each mode handles the maskable interrupts differently. Its years I use those but IIRC:
IM0
executes opc placed on databus by external HW
IM1
calls fixed ISR at 38h
IM2
calls ISR from ISR entry point table which is placed where i register points
Here relevant interrupt C++ code extracted from my emulator:
//---------------------------------------------------------------------------
void Z80::_reset()
{
im=0;
iff1=0;
iff2=0;
reg.r16.pc =0x0000;
reg.r16.af =0xFFFF;
reg.r16.bc =0xFFFF;
reg.r16.de =0xFFFF;
reg.r16.hl =0xFFFF;
reg.r16.ix =0xFFFF;
reg.r16.iy =0xFFFF;
reg.r16.ir =0xFFFF;
reg.r16.sp =0xFFFF;
reg.r16._af=0xFFFF;
reg.r16._bc=0xFFFF;
reg.r16._de=0xFFFF;
reg.r16._hl=0xFFFF;
reg.r16.alu=0xFFFF;
reg.r16.mem=0xFFFF;
reg.r16.io =0xFFFF;
reg.r16.nn =0xFFFF;
time=0; time0=0; dtime=0;
busrq=false;
busack=false;
}
//---------------------------------------------------------------------------
void Z80::_int()
{
if (!_enable_int) return;
if (!iff1) return;
if (actual->ins==_z80_ins_HALT) reg.r16.pc+=actual->size;
if ((actual->ins==_z80_ins_EI)||(actual->ins==_z80_ins_DI)) execute();
iff1=0;
iff2=0;
if (im==0)
{
// execute instruction on databus db from peripherials
mc=0;
actual=&ins_int0;
time+=actual->mc[mc]; mc++; // fetch INT
BYTE db[4];
db[0]=db8;
db[1]=db8;
db[2]=db8;
db[3]=db8;
execute(db);
}
else if (im==1)
{
mc=0;
actual=&ins_int1;
time+=actual->mc[mc]; mc++; // fetch INT
_push(reg.r16.pc);
reg.r16.pc=0x0038; // fixed vector 38h
}
else if (im==2)
{
mc=0;
actual=&ins_int2;
time+=actual->mc[mc]; mc++; // fetch INT
_push(reg.r16.pc);
union { BYTE db[2]; WORD dw; } ubw;
ubw.db[1]=reg.r8.i; // H
ubw.db[0]=db8; // L
reg.r16.pc=_readw(ubw.dw); // vector from mem[i+db8]
}
}
//---------------------------------------------------------------------------
void Z80::_nmi()
{
if (actual->ins==_z80_ins_HALT) reg.r16.pc+=actual->size;
if ((actual->ins==_z80_ins_EI)||(actual->ins==_z80_ins_DI)) execute();
iff2=iff1; // iff2 ide do flagov po ld a,i alebo ld a,r
iff1=0;
mc=0;
actual=&ins_nmi;
time+=actual->mc[mc]; mc++; // fetch NMI
_push(reg.r16.pc);
reg.r16.pc=0x0066; // fixed vector 66h
}
//---------------------------------------------------------------------------
Here all the IM instructions in order extracted from here What's the proper implementation for hardware emulation?:
opc T0 T1 MC1 MC2 MC3 MC4 MC5 MC6 MC7 mnemonic
ED46 08 00 M1R 4 M1R 4 ... 0 ... 0 ... 0 ... 0 ... 0 IM0
ED4E 08 00 M1R 4 M1R 4 ... 0 ... 0 ... 0 ... 0 ... 0 IM0
ED56 08 00 M1R 4 M1R 4 ... 0 ... 0 ... 0 ... 0 ... 0 IM1
ED5E 08 00 M1R 4 M1R 4 ... 0 ... 0 ... 0 ... 0 ... 0 IM2
ED66 08 00 M1R 4 M1R 4 ... 0 ... 0 ... 0 ... 0 ... 0 IM0
ED6E 08 00 M1R 4 M1R 4 ... 0 ... 0 ... 0 ... 0 ... 0 IM0
ED76 08 00 M1R 4 M1R 4 ... 0 ... 0 ... 0 ... 0 ... 0 IM1
ED7E 08 00 M1R 4 M1R 4 ... 0 ... 0 ... 0 ... 0 ... 0 IM2
As you can see its:
IM value: 0 0 1 2 0 0 1 2
And your linked page:
IM value: 0 0/1 1 2 0 0/1 1 2
so I expect it just mean how the opc is encoded but you right the tables there are not very obvious.
The IM0/1 are duplicates of IM0 so I am guessing they were not in original documentation and was discovered only latter ... without the exact behavior knowledge at that time your table was created... There are a lot of originally undocumented (secret) instructions so if your source of info does not contain them accurately maybe you should not use it and move to better docs to avoid problems and incompatibilities in future...

Related

How to switch between radians and degrees in SAS

just looking for an easy way to run trig functions in SAS without having to manually correct in each calculation. Below is what I am working with.
I am running this in SAS 9 probably, the SAS Studio Student Module but this is a general SAS question.
I have manually created a variable, 'rad' in the 'calc' data step to deal with this but it adds a step of complexity that I would like to avoid.
I am asking whether there is a system setting, alternate trig function or ... ? that would change the calculation from:
bh_x = cos(rad*bh_a)*bh_l ;
to:
bh_x = cos(bh_a)*bh_l ;
so I don't have to manually convert my angle in degrees to radians for the trig function to work.
Thanks to anyone reading this and putting any mental effort to the solution!
Tim
data spec ;
length
b2h_a 8
b2h_l 8
b2h_l_e 8
bike $ 8
name $ 16
;
input
bike $
name $
bh_a
bh_l
ht_a
spcr
st_h
st_a
st_l
hb_r
hb_a
;
datalines ;
srcn (0,0) 0 0 67 0 0 0 0 0 0
srcn c 41 658 71.5 27 40 25 120 100 13
srcn ne_27_n13 41 658 71.5 27 40 27 127 100 13
srcn ne_15_0 41 658 71.5 15 40 27 127 100 0
srcn ne_5_0 41 658 71.5 5 40 27 127 100 0
srcn ne_2_n9 41 658 71.5 2 40 27 127 100 9
srcn ne_5_10 41 658 71.5 5 40 27 127 100 -10
srcn ne_10_rf10 41 658 71.5 10 40 27 127 20 -10
srcn max 41 658 90 250 0 0 250 0 0
;
run ;
data calc ;
set spec ;
pi=constant('pi') ;
rad=pi/180 ;
bh_x = cos(rad*bh_a)*bh_l ;
bh_y = sin(rad*bh_a)*bh_l ;
sr_x = (cos(rad*ht_a)*(spcr+st_h/2))*-1 ;
sr_y = sin(rad*ht_a)*(spcr+st_h/2);
st_x = cos(rad*(90-ht_a+st_a))*st_l ;
st_y = sin(rad*(90-ht_a+st_a))*st_l ;
hb_x = cos(rad*(90-hb_a))*hb_r*-1 ;
hb_y = sin(rad*(90-hb_a))*hb_r ;
hd_x = bh_x + sr_x + st_x + hb_x ;
hd_y = bh_y + sr_y + st_y + hb_y ;
if hd_x=0 then do ;
b2h_a=0 ;
b2h_l=0 ;
end ;
else do ;
b2h_a = atan(hd_y/hd_x)/rad ;
b2h_l = hd_y/sin(b2h_a*rad) ;
end ;
b2h_l_e = b2h_l/25.4 ;
drop pi rad ;
format
b2h_a 5.
b2h_l 5.
b2h_l_e 5.
bh_a 5.
bh_l 5.
ht_a 5.
spcr 5.
st_h 5.
st_a 5.
st_l 5.
hb_r 5.
hb_a 5.
bh_x 5.
bh_y 5.
sr_x 5.
sr_y 5.
st_x 5.
st_y 5.
hb_x 5.
hb_y 5.
hd_x 5.
hd_y 5.
b2h_a 5.
b2h_l 5.
b2h_l_e 5.1
;
run ;
There are no trig functions in SAS that accept DEGREE or GRADIAN arguments. You always need to convert from your data's angular measurement system to RADIAN.
You can write a macro to perform the conversion. Example:
%macro cosD(theta);
%* theta is angle in degrees;
%* emit data step source code that performs conversion from degrees to radians;
cos(&theta*constant('PI')/180)
%mend;
In use:
data calc ;
set spec ;
bh_x = %cosD(bh_a) * bh_l ;
You could convert the angular data to radians during the step where input occurs and then not have to worry about it again.

how to optimize away common subexpressions?

select x+y as z,
case
when "x"+"y" < 0 then "Less Than Zero"
when "x"+"y" > 0 then "Non Zero"
else "Zero"
end
from sometable;
Returns expected result, but the addition is done with each row of data multiple times.
I am trying to optimize the query as follows but not working..
select x+y as z,
case
when "z" < 0 then "Less Than Zero"
when "z" > 0 then "Non Zero"
else "Zero"
end
from sometable;
Always returns "Less Than Zero".
What am I doing wrong on this query? How can I avoid adding A and B multiple times while the query is being executed?
Column aliases in the SELECT clause are not available in other expressions in the same SELECT clause. (What should happen with SELECT x AS y, y AS x ...?)
You can make such an alias available by moving it into a subquery:
SELECT z,
CASE WHEN z < 0 THEN 'Less Than Zero'
WHEN z > 0 THEN 'Non Zero'
ELSE 'Zero'
END
FROM (SELECT x + y AS z
FROM sometable);
However, this only saves typing; it does not actually optimize away the duplicate computation:
sqlite> explain select z, z from (select x+y as z from sometable);
addr opcode p1 p2 p3 p4 p5 comment
---- ------------- ---- ---- ---- ------------- -- -------------
0 Init 0 11 0 00 Start at 11
1 OpenRead 1 2 0 2 00 root=2 iDb=0; sometable
2 Rewind 1 9 0 00
3 Column 1 0 3 00 r[3]=sometable.x
4 Column 1 1 4 00 r[4]=sometable.y
5 Add 4 3 1 00 r[1]=r[4]+r[3]
6 Add 4 3 2 00 r[2]=r[4]+r[3]
7 ResultRow 1 2 0 00 output=r[1..2]
8 Next 1 3 0 01
9 Close 1 0 0 00
10 Halt 0 0 0 00
11 Transaction 0 0 1 0 01 usesStmtJournal=0
12 TableLock 0 2 0 sometable 00 iDb=0 root=2 write=0
13 Goto 0 1 0 00

Qt: How to implement "per minute" Timer? Better option to avoid misfire and double-fire?

I am using Qt5 on Windows7 platform.
In my current app I need a timer to fire every minute ("per minute"), from minute 00 to 59...
I have experimented various ideas, but my (previous) solutions had some issues like: misfire (no timeout triggered for a certain minute) or double-fire (timeout triggered twice for the same minute!).
Finally, I currently reached to this implementation:
static QTimer timer;
static int GetInterval()
{
QDateTime now(QDateTime::currentDateTime());
return ((60 - now.time().second()) * 1000 - now.time().msec());
}
void TEST_TIMER(void)
{
QObject::connect(&timer, &QTimer::timeout, []()
{
qDebug() << " Triggered! " << QDateTime::currentDateTime().time().minute()
<< QDateTime::currentDateTime().time().second()
<< QDateTime::currentDateTime().time().msec();
timer.start(GetInterval());
} );
timer.start(GetInterval());
}
And here is the output:
Triggered! 34 59 550
Triggered! 35 0 3
Triggered! 36 0 15
Triggered! 37 0 28
Triggered! 38 0 41
Triggered! 39 0 54
Triggered! 40 0 68
Triggered! 41 0 82
Triggered! 42 0 97
Triggered! 43 0 109
Triggered! 44 0 123
Triggered! 45 0 137
Triggered! 46 0 149
Triggered! 47 0 165
Triggered! 48 0 178
Triggered! 49 0 192
Triggered! 50 0 205
Triggered! 51 0 217
Triggered! 52 0 231
Triggered! 53 0 244
...
Seems ok, except the first line: Triggered! 34 59 550 :( Why?
Also, why is there that up-drift of about 12-13 msecs/minute?.
So, not being expert in this matter I prefer to ask:
Is this implementation ok? Can it be improved to avoid unpleasant situations like double-fire and/or misfire?
From QTimer description (Qt::CoarseTimer being the default):
For Qt::CoarseTimer and Qt::VeryCoarseTimer types, QTimer may wake up
earlier than expected, within the margins for those types: 5% of the
interval for Qt::CoarseTimer and 500 ms for Qt::VeryCoarseTimer.
So with a 5% accurary, your first shot can be much earlier than expected, and that explains:
Triggered! 34 59 550
Triggered! 35 0 3
If the timer shots (just) before the 0 minute, it will shoot again to align to the minute that's not yet reached, even if it's a few milliseconds away.
If you use a Qt::PreciseTimer instead, it will never time out earlier than expected, so you won't have this problem (pad the delay with a few ms to be sure).
The Qt::CoarseTimer also probably explains the small drift you're seeing, as nothing states that the error margin is random.
I need a timer to fire every minute
Why not keep things simple?
QTimer* pTimer = new QTimer;
connect(pTimer, &QTimer::timeout, [=](){
// do something
};
// fire every 60 seconds
// 1 * 1000 is every second
pTimer->Start(1 * 1000 * 60)
Note that a timer will keep firing, unless you set setSingleShot(true), stop the timer, or delete it.

Equivalent bitget function in R

Is there a function in R that performs the same operation as bitget in MatLab/Octave:
bitget
From the bitget help page
Return the status of bit(s) n of unsigned integers in A the
lowest significant bit is n = 1.
bitget (100, 8:-1:1)
⇒ 0 1 1 0 0 1 0 0
so if you want to get the bit values for an integer in R, you can do
intToBits(100)[8:1]
# [1] 00 01 01 00 00 01 00 00
That technically returns a raw vector, so if you want just a numeric vector, do
as.numeric(intToBits(100)[8:1])
# [1] 0 1 1 0 0 1 0 0

Does Gray code exist for other bases than two?

Just a matter of curiosity, is the Gray code defined for bases other than base two?
I tried to count in base 3, writing consecutive values paying attention to change only one trit at a time. I've been able to enumerate all the values up to 26 (3**3-1) and it seems to work.
000 122 200
001 121 201
002 120 202
012 110 212
011 111 211
010 112 210
020 102 220
021 101 221
022 100 222
The only issue I can see, is that all three trits change when looping back to zero. But this is only true for odd bases. When using even bases looping back to zero would only change a single digit, as in binary.
I even guess it can be extended to other bases, even decimal. This could lead to another ordering when counting in base ten ... :-)
0 1 2 3 4 5 6 7 8 9 19 18 17 16 15 14 13 12 11 10
20 21 22 23 24 25 26 27 28 29 39 38 37 36 35 34 33 32 31 30
Now the question, has anyone ever heard of it? Is there an application for it? Or it is just mathematical frenzy?
Yes. Have a look at the Gray code article at wikipedia. It has a section on n-ary Gray Code.
There are many specialized types of Gray codes other than the binary-reflected Gray code. One such type of Gray code is the n-ary Gray code, also known as a non-Boolean Gray code. As the name implies, this type of Gray code uses non-Boolean values in its encodings.
Just for completeness (as aioobe already gave the right answer), here's a C++ program that lists all the 168 2-digit gray codes for base 3 that start with 00 and marks the 96 cyclic ones. Using the algorithm from Wikipedia, you can construct longer Gray codes easily for even bases. For uneven bases, you can change the program to generate according Gray codes.
The first cyclic 2-digit gray code found with this program is this one:
00 01 02 12 10 11 21 22 20
After changing the program, the first cyclic 3-digit gray found is this:
000 001 002 012 010 011 021 020 022 122 102 100 101 111
110 112 212 202 222 220 120 121 221 201 211 210 200
Code:
#include <stdio.h>
#include <stdlib.h>
// Highest number using two trits
#define MAXN 9
int gray_code_count, cyclic_count;
bool changes_one_trit(int code1, int code2) {
int trits_changed = 0;
if ((code1 / 3) != (code2 / 3)) trits_changed++;
if ((code1 % 3) != (code2 % 3)) trits_changed++;
return (trits_changed == 1);
}
int generate_gray_code(int* code, int depth) {
bool already_used;
if (depth == MAXN) {
for (int i = 0; i < MAXN; i++) {
printf("%i%i ", code[i]/3, code[i]%3);
}
// check if cyclic
if (changes_one_trit(code[MAXN-1], 0)) {
printf("cyclic");
cyclic_count++;
}
printf("\n");
gray_code_count++;
}
// Iterate through the codes that only change one trit
for (int i = 0; i < MAXN; i++) {
// Check if it was used already
already_used = false;
for (int j = 0; j < depth; j++) {
if (code[j] == i) already_used = true;
}
if (already_used) continue;
if (changes_one_trit(code[depth-1], i)) {
code[depth] = i;
generate_gray_code(code, depth + 1);
}
}
}
int main() {
int* code = (int*)malloc(MAXN * sizeof(int));
code[0] = 0;
gray_code_count = 0;
generate_gray_code(code, 1);
printf("%i gray codes found, %i of them are cyclic\n", gray_code_count, cyclic_count);
free(code);
}

Resources