Jump to content
IGNORED

Bird's nest...


Recommended Posts

Still turning the crank on the software...I've tested most of the boundary conditions for sprite exclusion and they're working, though I can think of some more tests I can run. I've also started more testing of the experimental emulator. So far it's passing my speed tests, which is a good thing. I've only tested the actual functionality of a few opcodes so far, but I've also done a major reorganization of my extended opcodes to make them more standardized. I'm putting together a reference that I can post here, but keep in mind that it's subject to change.

 

INSTRUCTION		OPCODE			LOGIC					NOTES
-----------------------------------------------------------------------------------------------------
HLT			000000 0000 000 000	halt cpu
SDBD			000000 0000 000 001	sdbd_mode = true
EIS			000000 0000 000 010	enable_interrupts
DIS			000000 0000 000 011	disable_interrupts
J       (RB,)DEST(,e/d)	000000 0000 000 100	j/jsr [rb] ena/dis interrupts
TCI			000000 0000 000 101
CLRC			000000 0000 000 110	C = 0
SETC			000000 0000 000 111	C = 1
INCR      RD		000000 0000 001 ddd	RD++
DECR      RD		000000 0000 010 ddd	RD--
COMR      RD		000000 0000 011 ddd	RD = ~RD
NEGR      RD		000000 0000 100 ddd	RD = -RD
ADCR      RD		000000 0000 101 ddd	RD += C
GSWD      RR		000000 0000 110 0rr
NOP     		000000 0000 110 10m						6
SIN     		000000 0000 110 11m						6
RSWD      RS		000000 0000 111 sss
SHX       type,RR(,2)	000000 0001 hhh mrr	RR shx= 1/2
MOVR      RS,RD		000000 0010 sss ddd	RD = RS
ADDR      RS,RD		000000 0011 sss ddd	RD += RS
SUBR      RS,RD		000000 0100 sss ddd	RD -= RS
CMPR      RS,RD		000000 0101 sss ddd	set_flags(RD - RS)
ANDR      RS,RD		000000 0110 sss ddd	RD &= RS
XORR      RS,RD		000000 0111 sss ddd	RD ^= RS
B         DISP(,E)	000000 1000 ze cccc	if cond: R7+=disp/-=(disp+1)
MVO       RS,dst	000000 1001 xxx sss	dst = RS				1
MVI       src,RD	000000 1010 xxx ddd	RD = src				1
ADD       src,RD	000000 1011 xxx ddd	RD += src				1
SUB       src,RD	000000 1100 xxx ddd	RD -= src				1
CMP       src,RS	000000 1101 xxx sss	set_flags(RD - src)			1
AND       src,RD	000000 1110 xxx ddd	RD &= src				1
XOR       src,RD	000000 1111 xxx ddd	RD ^= src				1
OR@       RM,RD		000001 0000 mmm ddd	RD |= [RM]				2
ANDN@     RM,RD		000001 0001 mmm ddd	RD &= ~[RM]				2
XORN@     RM,RD		000001 0010 mmm ddd	RD ^= ~[RM]				2
ORN@      RM,RD		000001 0011 mmm ddd	RD |= ~[RM]				2
NAND@     RM,RD		000001 0100 mmm ddd	RD = ~(RD & [RM])			2
XNOR@     RM,RD		000001 0101 mmm ddd	RD = ~(RD ^ [RM])			2
NOR@      RM,RD		000001 0110 mmm ddd	RD = ~(RD | [RM])			2
TST@      RM,RD		000001 0111 mmm ddd	set_flags(RD & [RM])			2
XCHG@     RM,RD		000001 1000 mmm ddd	RD <--> [RM]				2
ADC@      RM,RD		000001 1010 mmm ddd	RD += [RM] + C				2
SBC@      RM,RD		000001 1011 mmm ddd	RD -= ([RM] + ~C)			2
SLL@      RM,RD		000001 1100 mmm ddd	RD <<= [RM]				2
SLR@      RM,RD		000001 1101 mmm ddd	RD >>= [RM]				2
SAR@      RM,RD		000001 1110 mmm ddd	RD >>>= [RM]				2
ROL@      RM,RD		000001 1111 mmm ddd	RD rol= [RM]				2
ROR@      RM,RD		000010 0000 mmm ddd	RD ror= [RM]				2
MUL@      RM,RD		000010 0001 mmm ddd	RD *= [RM]				2, 4
IMUL@     RM,RD		000010 0010 mmm ddd	RD *= [RM]				2, 5
DIV@      RM,RD		000010 0011 mmm ddd	RD /= [RM]				2, 4
IDIV@     RM,RD		000010 0100 mmm ddd	RD /= [RM]				2, 5
REM@      RM,RD		000010 0100 mmm ddd	RD = RD % [RM]				2, 4
IREM@     RM,RD		000010 0110 mmm ddd	RD = RD % [RM]				2, 5
MAX@      RM,RD		000010 0111 mmm ddd	RD = max(RD,[RM])			2, 4
IMAX@     RM,RD		000010 1000 mmm ddd	RD = max(RD,[RM])			2, 5
MIN@      RM,RD		000010 1010 mmm ddd	RD = min(RD,[RM])			2, 4
IMIN@     RM,RD		000010 1011 mmm ddd	RD = min(RD,[RM])			2, 5
MVOC@     RS,dst	000010 1100 xxx sss	dst = ~RD				1
MVON@     RS,dst	000010 1101 xxx sss	dst = -RD				1
MVI@      src+RD,RD	000010 1110 xxx ddd	RD = [src + RD]				1, 3
MVI@      src+2*RD,RD	000010 1111 xxx ddd	RD = [src + 2 * RD]			1, 3
ORR       RS,RD		000011 0000 sss ddd	RD |= RS
ANDNR     RS,RD		000011 0001 sss ddd	RD &= ~RS
XORNR     RS,RD		000011 0010 sss ddd	RD ^= ~RS
ORNR      RS,RD		000011 0011 sss ddd	RD |= ~RS
NANDR     RS,RD		000011 0100 sss ddd	RD = ~(RD & RS)
XNORR     RS,RD		000011 0101 sss ddd	RD = ~(RD ^ RS)
NORR      RS,RD		000011 0110 sss ddd	RD = ~(RD | RS)
INCLR     RD		000011 0111 ddd ddd	lowbyte(RD)++				7
TSTR      RA,RB		000011 0111 aaa bbb	set_flags(RA & RB)			8
DECLR     RD		000011 1000 ddd ddd	lowbyte(RD)--				7
XCHGR     RA,RB		000011 1000 aaa bbb	RA <--> RB				8
ADCR      RS,RD		000011 1010 sss ddd	RD += RS + C
SBCR      RS,RD		000011 1011 sss ddd	RD -= (RS + ~C)
SLLR      RD,RA		000011 1100 ddd aaa	RD <<= RA
SLRR      RD,RA		000011 1101 ddd aaa	RD >>= RA
SARR      RD,RA		000011 1110 ddd aaa	RD >>>= RA
ROLR      RD,RA		000011 1111 ddd aaa	RD rol= RA
RORR      RD,RA		000100 0000 ddd aaa	RD ror= RA
MULR      RD,RA		000100 0001 sss ddd	RD *= RS				4
IMULR     RD,RA		000100 0010 sss ddd	RD *= RS				5
DIVR      RD,RA		000100 0011 sss ddd	RD /= RS				4
IDIVR     RD,RA		000100 0100 sss ddd	RD /= RS				5
REMR      RD,RA		000100 0101 sss ddd	RD = RD % RS				4
IDEMR     RD,RA		000100 0110 sss ddd	RD = RD % RS				5
MAXR      RS,RD		000100 0111 sss ddd	RD = max(RD,RS)				4
IMAXR     RS,RD		000100 1000 sss ddd	RD = max(RD,RS)				5
MINR      RS,RD		000100 1010 sss ddd	RD = min(RD,RS)				4
IMINR     RS,RD		000011 1011 sss ddd	RD = min(RD,RS)				5
FPIMULR   RS,RD		000100 1100 sss ddd	RD *= RS				5, 9
FPIDIVR   RS,RD		000100 1101 sss ddd	RD /= RS				5, 9
FPIREMR   RS,RD		000100 1110 sss ddd	RD = RD % RS				5, 9
MULRW     RA,RB		000100 1111 aaa bbb	R1:R0 = RA * RB				4, 10
IMULRW    RA,RB		000101 0000 aaa bbb	R1:R0 = RA * RB				5, 10
DIVRW     RV,RD		000101 0001 aaa bbb	R0 = RD / RV; R1 = RD % RV		4
IDIVRW    RV,RD		000101 0010 aaa bbb	R0 = RD / RV; R1 = RD % RV		5
UNPR      RB,RA		000101 0011 bbb aaa	RB = RA >> 8; RA &= 0xFF		11
PCKR      RS,RD		000101 0100 sss ddd	RA = (RA & 0xFF) | (RB << 8)		12
SBCR      RD		000101 0101 000 ddd	RD -= C
B2AH      RD		000101 0101 001 ddd	RD = ascii_hex(RD)			13
SHLD      RD:R0,a	000101 0101 dd aaaa	RD = (RD << a) | (R0 >> (16-a))		14
AH2B      RD		000101 0110 000 ddd	RD = value_of(RD)			15
DIV5      RD		000101 0110 001 ddd	RD /= 5					4
SHRD      RS:R0,a	000101 0110 ss aaaa	R0 = (R0 >> a) | (RS >> (16-a))		16
MVID@     RM+disp16,RD	000101 0111 mmm ddd	RD = [RM + disp16]			17
MVOD@     RM+disp16,RS	000101 1000 mmm sss	[RM + disp16] = RS			17
VMOV@@    RMS,RMD	000101 1010 mmm ddd	v3d[RMD] = v3d[RMS]			18
LOOP      RD,dest	000101 1010 ddd ddd	RD--; R7 += disp16 if RD != 0		19
BA/BNBE	  dest		000101 1010 110 110	R7 += disp16 if ((C or Z) = 0)
BNA/BBE	  dest		000101 1010 111 111	R7 += disp16 if ((C or Z) = 1)
DADD@@    RMS,RMD	000101 1011 sss ddd	[RMD] += [RMS]				20
DSUB@@    RMS,RMD	000101 1100 sss ddd	[RMD] -= [RMS]				20
CL0R      RD		000101 1101 000 ddd	RD = count_leading_zeroes(RD)		21
CL1R      RD		000101 1101 001 ddd	RD = count_leading_ones(RD)		22
CT0R      RD		000101 1101 010 ddd	RD = count_trailing_zeroes(RD)		23
CT1R      RD		000101 1101 011 ddd	RD = count_trailing_ones(RD)		24
SUBGER0	  RD		000101 1101 100 ddd	if RD >= R0, RD -= R0			4
DIV3      RD		000101 1101 101 ddd	RD /= 3					4
DIV100    RD		000101 1101 110 ddd	RD /= 100				4
DUPLR     RD		000101 1101 111 ddd	RD = (RD & 0xFF) | (RD << 8)
FPMULD@@  RMS,RMD	000101 1110 sss ddd	[RMD] *= [RMS]				4, 20
IFPMULD@@ RMS,RMD	000101 1111 sss ddd	[RMD] *= [RMS]				5, 20
MVO@      R0,RS		000110 0000 000 sss	[R0] = RS
MVI@      R0,RD		000110 0000 001 ddd	RD = [R0]
ADD@      R0,RD		000110 0000 010 ddd	RD += [R0]
SUB@      R0,RD		000110 0000 011 ddd	RD -= [R0]
CMP@      R0,RD		000110 0000 100 ddd	set_flags(RD - [R0])
AND@      R0,RD		000110 0000 101 ddd	RD &= [R0]
XOR@      R0,RD		000110 0000 110 ddd	RD ^= [R0]
MVOC@     R0,RS		000110 0000 111 sss	[R0] = ~RS
MVON@     R0,RS		000110 0001 000 sss	[R0] = -RS
MVI@      R0+RD,RD	000110 0001 001 ddd	RD = [R0 + RD]
MVI@      R0+2*RD,RD	000110 0001 010 ddd	RD = [R0 + 2 * RD]
ABSR      RD		000110 0001 011 ddd	RD = |RD|
NABSR     RD		000110 0001 100 ddd	RD = -|RD|
POW2R     RD		000110 0001 101 ddd	RD = 1 << RD				25
SGNR      RD		001010 0001 110 ddd	RD = sign(RD)				5, 26
ABSD@     RMD		000110 0001 111 ddd	[RMD] = |[RMD]|				5, 20
OR        ADDR, RD	000110 0010 000 ddd	RD |= [ADDR]				27
ANDN      ADDR, RD	000110 0010 001 ddd	RD &= ~[ADDR]				27
XORN      ADDR, RD	000110 0010 010 ddd	RD ^= ~[ADDR]				27
ORN       ADDR, RD	000110 0010 011 ddd	RD |= ~[ADDR]				27
NAND      ADDR, RD	000110 0010 100 ddd	RD = ~(RD & [ADDR])			27
XNOR      ADDR, RD	000110 0010 101 ddd	RD = ~(RD ^ [ADDR])			27
NOR       ADDR, RD	000110 0010 110 ddd	RD = ~(RD | [ADDR])			27
TST       ADDR, RD	000110 0010 111 ddd	set_flags(RD & [ADDR])			27
XCHG      ADDR, RD	000110 0011 000 ddd	RD <--> [ADDR]				27
ADC       ADDR, RD	000110 0011 001 ddd	RD += [ADDR] + C			27
SBC       ADDR, RD	000110 0011 010 ddd	RD -= ([ADDR] + ~C)			27
SLL       RD,ADDR	000110 0011 011 ddd	RD <<= [ADDR]				27
SLR       RD,ADDR	000110 0011 100 ddd	RD >>= [ADDR]				27
SAR       RD,ADDR	000110 0011 101 ddd	RD >>>= [ADDR]				27
ROL       RD,ADDR	000110 0011 110 ddd	RD rol= [ADDR]				27
ROR       RD,ADDR	000110 0011 111 ddd	RD ror= [ADDR]				27
MUL       ADDR,RD	000110 0100 000 ddd	RD *= [ADDR]				4, 27
IMUL      ADDR,RD	000110 0100 001 ddd	RD *= [ADDR]				5, 27
DIV       ADDR,RD	000110 0100 010 ddd	RD /= [ADDR]				4, 27
IDIV      ADDR,RD	000110 0100 011 ddd	RD /= [ADDR]				5, 27
REM       ADDR,RD	000110 0100 100 ddd	RD = RD % [ADDR]			4, 27
IREM      ADDR,RD	000110 0100 101 ddd	RD = RD % [ADDR]			5, 27
FPMULD@@  ADDR,RMD	000110 0100 110 ddd	[RMD] *= [ADDR]				4, 27, 28
IFPMULD@@ ADDR,RMD	000110 0100 111 ddd	[RMD] *= [ADDR]				5, 27, 28
VMOV@@    ADDR,RMD	000110 0101 000 ddd	v3d[RMD] = v3d[ADDR]			18, 27
DADD@@    ADDR,RMD	000110 0101 001 ddd	[RMD] += [ADDR]				20, 27
DSUB@@    ADDR,RMD	000110 0101 010 ddd	[RMD] -= [ADDR]				20, 27
LOOPE     RD,dest	000110 0101 011 ddd	RD--; R7 += disp16 if RD!=0 & Z=1	19
BREVR     R0		000110 0101 011 110	R0 = bit_reverse(R0)
BREVR     R1		000110 0101 011 111	R1 = bit_reverse(R1)
LOOPNE    RD,dest	000110 0101 100 ddd	RD--; R7 += disp16 if RD!=0 & Z=0	19
BREVR     R2		000110 0101 100 110	R2 = bit_reverse(R2)
BREVR     R3		000110 0101 100 111	R3 = bit_reverse(R3)
LOOPS     RD,dest	000110 0101 101 ddd	RD--; R7 += disp16 if RD!=0 & S=1	19
BREVR     R4		000110 0101 101 110	R4 = bit_reverse(R4)
BREVR     R5		000110 0101 101 111	R5 = bit_reverse(R5)
LOOPNS    RD,dest	000110 0101 110 ddd	RD--; R7 += disp16 if RD!=0 & S=0	19
COMC			000110 0101 110 110	C = !C
ENAEXT			000110 0101 110 111	enable_extended_opcodes			29
DBTR      RD		000110 0101 111 ddd	RD = double_bits(RD)			30
REV4R     RD		000110 0110 000 ddd	RD = RD[3:0][7:4][11:8][15:12]		31
REV4HR    RD		000110 0110 001 ddd	RD = RD[11:8][15:12][3:0][7:4]		32
FPINVD@   RMD		000110 0110 010 ddd	[RMD] = 1/[RMD]				5, 28
MVOIA     DATA, ADDR	000110 0110 011 000	[ADDR] = DATA				33
ADDIA     DATA, ADDR	000110 0110 011 001	[ADDR] += DATA				33
SUBIA     DATA, ADDR	000110 0110 011 010	[ADDR] -= DATA				33
CMPIA     DATA, ADDR	000110 0110 011 011	set_flags([ADDR] - DATA)		33
ANDIA     DATA, ADDR	000110 0110 011 100	[ADDR] &= DATA				33
XORIA     DATA, ADDR	000110 0110 011 101	[ADDR] ^= DATA				33
ORIA      DATA, ADDR	000110 0110 011 110	[ADDR] |= DATA				33
ANDNIA    DATA, ADDR	000110 0110 011 111	[ADDR] &= ~DATA				33
XORNIA    DATA, ADDR	000110 0110 100 000	[ADDR] ^= ~DATA				33
ORNIA     DATA, ADDR	000110 0110 100 001	[ADDR] |= ~DATA				33
NANDIA    DATA, ADDR	000110 0110 100 010	[ADDR] = ~([ADDR] & DATA)		33
XNORIA    DATA, ADDR	000110 0110 100 011	[ADDR] = ~([ADDR] ^ DATA)		33
NORIA     DATA, ADDR	000110 0110 100 100	[ADDR] = ~([ADDR] | DATA)		33
TSTIA     DATA, ADDR	000110 0110 100 101	set_flags([ADDR] & DATA)		33
XCHGIA    DATA, ADDR	000110 0110 100 110	[ADDR] <--> DATA			33, 34
ADCIA     DATA, ADDR	000110 0110 100 111	[ADDR] += DATA + C			33
SBCIA     DATA, ADDR	000110 0110 101 000	[ADDR] -= (DATA + ~C)			33
SLLIA     DATA, ADDR	000110 0110 101 001	[ADDR] <<= DATA				33
SLRIA     DATA, ADDR	000110 0110 101 010	[ADDR] >>= DATA				33
SARIA     DATA, ADDR	000110 0110 101 011	[ADDR] >>>= DATA			33
ROLIA     DATA, ADDR	000110 0110 101 100	[ADDR] rol= DATA			33
RORIA     DATA, ADDR	000110 0110 101 101	[ADDR] ror= DATA			33
MULIA     DATA, ADDR	000110 0110 101 110	[ADDR] *= DATA				4, 33
IMULIA    DATA, ADDR	000110 0110 101 111	[ADDR] *= DATA				5, 33
DIVIA     DATA, ADDR	000110 0110 110 000	[ADDR] /= DATA				4, 33
IDIVIA    DATA, ADDR	000110 0110 110 001	[ADDR] /= DATA				5, 33
REMIA     DATA, ADDR	000110 0110 110 010	[ADDR] = [ADDR] % DATA			4, 33
IREMIA    DATA, ADDR	000110 0110 110 011	[ADDR] = [ADDR] % DATA			5, 33
SWAP      RD		000110 0110 110 1dd	swap_bytes(RD)				35
STCP      RD		000110 0110 111 ddd	C = parity(RD)				36
DISEXT			000110 0110 111 111	disable_extended_opcodes		29
POW10RL   RD		000110 0111 000 ddd	RD = low_word(pow(10,RD))		37
POW10RH   RD		000110 0111 001 ddd	RD = high_word(pow(10,RD))		37
FPISQRTR  RD		000110 0111 010 ddd	RD = 1 / sqrt(RD)			4, 9, 38
  
  Notes
-----

1.  If xxx is 0, uses direct addressing instead (@R0 is not supported).
2.  @R0 is supported.  Direct addressing is handled by a different opcode.
3.  Src is not altered.  Auto-increment for SDBD purposes arises from RD
    (Src is the base address, RD is the index address).
4.  Operands are treated as unsigned.
5.  Operands are treated as signed.
6.  m should have no effect
7.  Changes the low byte only, leaving the high byte unaltered.
8.  aaa is always different from bbb
9.  Operands are treated as 16-bit fixed-point numbers in 8.8 format.
10. Produces a 32-bit result with the high word placed in R1 and the low word placed in R0.
11. Unpacks the two bytes in RA into RA and RB.
12. Packs the low bytes of RA and RB into RA.
13. RD <-- hexadecimal ASCII representation of the low byte of RD (e.g. 0x000A --> 3041 "0A")
14. Shifts bits from R0 into RD.  R0 is unaltered.  RD may be in the range R1..R3.
15. RD = binary value (0..255) of hexadecimal ASCII characters stored in RD.  Invalid
    characters in a byte result in that byte being interpreted as 0 (e.g. 3041 --> 0x0A,
    2F41 --> 0x0A). Ignores case.
16. Shifts bits from RS into R0. RS is unaltered. C = low bit of R0 shifted out if a > 0.
    RS may be in the range R1..R3.
17. Does ***not*** change RM if mmm>3. Supports SDBD.
18. Copies a 3-vector from [Src] to [RMD].  Each vector component is 32 bits, for a total
    copy of 6 words.
19. ddd < 6
20. Operands are 32 bits in size.
21. RD = number of consecutive 0 bits in RD starting at the MSB
22. RD = number of consecutive 1 bits in RD starting at the MSB
23. RD = number of consecutive 0 bits in RD starting at the LSB
24. RD = number of consecutive 1 bits in RD starting at the LSB
25. If RD > 15, result is 0.
26. Result is either -1, 0, or 1.
27. Direct addressing mode version.
28. Operands are treated as 32-bit fixed-point values in 16.16 format.
29. No effect in the emulator (extended opcodes are always active).  Reserved for a
    physical CPU.
30. RD = doubled bits of low byte of RD (e.g. 0x0011 --> 0x0303)
31. Reverses the order of the 4-bit nibbles in RD (e.g. 0x0123 --> 0x3120).
32. Reverses the order of the 4-bit nibbles in each byte of RD (e.g. 0x0123 --> 0x1032).
33. Three-word instruction: the second word is an address and the third word is an immediate
    value.  SDBD is not supported.
34. If running from ROM, net effect is [ADDR] = DATA.
35. RD is indexed by dd + 4, i.e. RD is in the range R4..R7.
36. ddd <> 7.  If RD contains an odd number of 1 bits, C = 1, else C = 0 (sets carry as RD parity)
37. If RD > 9, the result is 0.
38. Uses fast-inverse-square-root approximation algorithm with one iteration.

 

Edited by JohnPCAE
Link to comment
Share on other sites

Below is the final specification for emulated instructions in the software. I've tested only a handful, so there's some testing ahead. I might not wait to complete that before making everything public though since new software is easy to drop into the Pico. Going forward, I have to build the final versions of the hardware design to verify them, and then it should be time to make everything public.

 

==========================================================================
OVERLAY VIDEO EXTENDED INSTRUCTION SET
==========================================================================

INSTRUCTION		OPCODE			LOGIC					NOTES
-----------------------------------------------------------------------------------------------------
HLT			000000 0000 000 000	halt cpu
SDBD			000000 0000 000 001	sdbd_mode = true
EIS			000000 0000 000 010	enable_interrupts
DIS			000000 0000 000 011	disable_interrupts
J       (RB,)DEST(,e/d)	000000 0000 000 100	j/jsr [rb] ena/dis interrupts
TCI			000000 0000 000 101
CLRC			000000 0000 000 110	C = 0
SETC			000000 0000 000 111	C = 1
INCR      RD		000000 0000 001 ddd	RD++
DECR      RD		000000 0000 010 ddd	RD--
COMR      RD		000000 0000 011 ddd	RD = ~RD
NEGR      RD		000000 0000 100 ddd	RD = -RD
ADCR      RD		000000 0000 101 ddd	RD += C
GSWD      RR		000000 0000 110 0rr
NOP     		000000 0000 110 10m						6
SIN     		000000 0000 110 11m						6
RSWD      RS		000000 0000 111 sss
SHX       type,RR(,2)	000000 0001 hhh mrr	RR shx= 1/2
MOVR      RS,RD		000000 0010 sss ddd	RD = RS
ADDR      RS,RD		000000 0011 sss ddd	RD += RS
SUBR      RS,RD		000000 0100 sss ddd	RD -= RS
CMPR      RS,RD		000000 0101 sss ddd	set_flags(RD - RS)
ANDR      RS,RD		000000 0110 sss ddd	RD &= RS
XORR      RS,RD		000000 0111 sss ddd	RD ^= RS
B         DISP(,E)	000000 1000 ze cccc	if cond: R7+=disp/-=(disp+1)
MVO       RS,dst	000000 1001 xxx sss	dst = RS				1
MVI       src,RD	000000 1010 xxx ddd	RD = src				1
ADD       src,RD	000000 1011 xxx ddd	RD += src				1
SUB       src,RD	000000 1100 xxx ddd	RD -= src				1
CMP       src,RS	000000 1101 xxx sss	set_flags(RD - src)			1
AND       src,RD	000000 1110 xxx ddd	RD &= src				1
XOR       src,RD	000000 1111 xxx ddd	RD ^= src				1
OR@       RM,RD		000001 0000 mmm ddd	RD |= [RM]				2
ANDN@     RM,RD		000001 0001 mmm ddd	RD &= ~[RM]				2
XORN@     RM,RD		000001 0010 mmm ddd	RD ^= ~[RM]				2
ORN@      RM,RD		000001 0011 mmm ddd	RD |= ~[RM]				2
NAND@     RM,RD		000001 0100 mmm ddd	RD = ~(RD & [RM])			2
XNOR@     RM,RD		000001 0101 mmm ddd	RD = ~(RD ^ [RM])			2
NOR@      RM,RD		000001 0110 mmm ddd	RD = ~(RD | [RM])			2
TST@      RM,RD		000001 0111 mmm ddd	set_flags(RD & [RM])			2
XCHG@     RM,RD		000001 1000 mmm ddd	RD <--> [RM]				2
ADC@      RM,RD		000001 1010 mmm ddd	RD += [RM] + C				2
SBC@      RM,RD		000001 1011 mmm ddd	RD -= ([RM] + ~C)			2
SLL@      RM,RD		000001 1100 mmm ddd	RD <<= [RM]				2
SLR@      RM,RD		000001 1101 mmm ddd	RD >>= [RM]				2
SAR@      RM,RD		000001 1110 mmm ddd	RD >>>= [RM]				2
ROL@      RM,RD		000001 1111 mmm ddd	RD rol= [RM]				2
ROR@      RM,RD		000010 0000 mmm ddd	RD ror= [RM]				2
MUL@      RM,RD		000010 0001 mmm ddd	RD *= [RM]				2, 4
IMUL@     RM,RD		000010 0010 mmm ddd	RD *= [RM]				2, 5
DIV@      RM,RD		000010 0011 mmm ddd	RD /= [RM]				2, 4
IDIV@     RM,RD		000010 0100 mmm ddd	RD /= [RM]				2, 5
REM@      RM,RD		000010 0100 mmm ddd	RD = RD % [RM]				2, 4
IREM@     RM,RD		000010 0110 mmm ddd	RD = RD % [RM]				2, 5
MAX@      RM,RD		000010 0111 mmm ddd	RD = max(RD,[RM])			2, 4
IMAX@     RM,RD		000010 1000 mmm ddd	RD = max(RD,[RM])			2, 5
MIN@      RM,RD		000010 1010 mmm ddd	RD = min(RD,[RM])			2, 4
IMIN@     RM,RD		000010 1011 mmm ddd	RD = min(RD,[RM])			2, 5
MVOC@     RS,dst	000010 1100 xxx sss	dst = ~RD				1
MVON@     RS,dst	000010 1101 xxx sss	dst = -RD				1
MVI@      src+RD,RD	000010 1110 xxx ddd	RD = [src + RD]				1, 3
MVI@      src+2*RD,RD	000010 1111 xxx ddd	RD = [src + 2 * RD]			1, 3
ORR       RS,RD		000011 0000 sss ddd	RD |= RS
ANDNR     RS,RD		000011 0001 sss ddd	RD &= ~RS
XORNR     RS,RD		000011 0010 sss ddd	RD ^= ~RS
ORNR      RS,RD		000011 0011 sss ddd	RD |= ~RS
NANDR     RS,RD		000011 0100 sss ddd	RD = ~(RD & RS)
XNORR     RS,RD		000011 0101 sss ddd	RD = ~(RD ^ RS)
NORR      RS,RD		000011 0110 sss ddd	RD = ~(RD | RS)
INCLR     RD		000011 0111 ddd ddd	lowbyte(RD)++				7
TSTR      RA,RB		000011 0111 aaa bbb	set_flags(RA & RB)			8
DECLR     RD		000011 1000 ddd ddd	lowbyte(RD)--				7
XCHGR     RA,RB		000011 1000 aaa bbb	RA <--> RB				8
ADCR      RS,RD		000011 1010 sss ddd	RD += RS + C
SBCR      RS,RD		000011 1011 sss ddd	RD -= (RS + ~C)
SLLR      RD,RA		000011 1100 ddd aaa	RD <<= RA
SLRR      RD,RA		000011 1101 ddd aaa	RD >>= RA
SARR      RD,RA		000011 1110 ddd aaa	RD >>>= RA
ROLR      RD,RA		000011 1111 ddd aaa	RD rol= RA
RORR      RD,RA		000100 0000 ddd aaa	RD ror= RA
MULR      RD,RA		000100 0001 sss ddd	RD *= RS				4
IMULR     RD,RA		000100 0010 sss ddd	RD *= RS				5
DIVR      RD,RA		000100 0011 sss ddd	RD /= RS				4
IDIVR     RD,RA		000100 0100 sss ddd	RD /= RS				5
REMR      RD,RA		000100 0101 sss ddd	RD = RD % RS				4
IDEMR     RD,RA		000100 0110 sss ddd	RD = RD % RS				5
MAXR      RS,RD		000100 0111 sss ddd	RD = max(RD,RS)				4
IMAXR     RS,RD		000100 1000 sss ddd	RD = max(RD,RS)				5
MINR      RS,RD		000100 1010 sss ddd	RD = min(RD,RS)				4
IMINR     RS,RD		000011 1011 sss ddd	RD = min(RD,RS)				5
FPIMULR   RS,RD		000100 1100 sss ddd	RD *= RS				5, 9
FPIDIVR   RS,RD		000100 1101 sss ddd	RD /= RS				5, 9
FPIREMR   RS,RD		000100 1110 sss ddd	RD = RD % RS				5, 9
MULRW     RA,RB		000100 1111 aaa bbb	R1:R0 = RA * RB				4, 10
IMULRW    RA,RB		000101 0000 aaa bbb	R1:R0 = RA * RB				5, 10
DIVRW     RV,RD		000101 0001 aaa bbb	R0 = RD / RV; R1 = RD % RV		4
IDIVRW    RV,RD		000101 0010 aaa bbb	R0 = RD / RV; R1 = RD % RV		5
UNPR      RB,RA		000101 0011 bbb aaa	RB = RA >> 8; RA &= 0xFF		11
PCKR      RS,RD		000101 0100 sss ddd	RA = (RA & 0xFF) | (RB << 8)		12
SBCR      RD		000101 0101 000 ddd	RD -= C
B2AH      RD		000101 0101 001 ddd	RD = ascii_hex(RD)			13
SHLD      RD:R0,a	000101 0101 dd aaaa	RD = (RD << a) | (R0 >> (16-a))		14
AH2B      RD		000101 0110 000 ddd	RD = value_of(RD)			15
DIV5      RD		000101 0110 001 ddd	RD /= 5					4
SHRD      RS:R0,a	000101 0110 ss aaaa	R0 = (R0 >> a) | (RS >> (16-a))		16
MVID@     RM+disp16,RD	000101 0111 mmm ddd	RD = [RM + disp16]			17
MVOD@     RM+disp16,RS	000101 1000 mmm sss	[RM + disp16] = RS			17
VMOV@@    RMS,RMD	000101 1010 mmm ddd	v3d[RMD] = v3d[RMS]			18
LOOP      RD,dest	000101 1010 ddd ddd	RD--; R7 += disp16 if RD != 0		19
BA/BNBE	  dest		000101 1010 110 110	R7 += disp16 if (C = 1) and (Z = 0)
BNA/BBE	  dest		000101 1010 111 111	R7 += disp16 if (C = 0) or (Z = 1)
DADD@@    RMS,RMD	000101 1011 sss ddd	[RMD] += [RMS]				20
DSUB@@    RMS,RMD	000101 1100 sss ddd	[RMD] -= [RMS]				20
CL0R      RD		000101 1101 000 ddd	RD = count_leading_zeroes(RD)		21
CL1R      RD		000101 1101 001 ddd	RD = count_leading_ones(RD)		22
CT0R      RD		000101 1101 010 ddd	RD = count_trailing_zeroes(RD)		23
CT1R      RD		000101 1101 011 ddd	RD = count_trailing_ones(RD)		24
SUBGER0	  RD		000101 1101 100 ddd	if RD >= R0, RD -= R0			4
DIV3      RD		000101 1101 101 ddd	RD /= 3					4
DIV100    RD		000101 1101 110 ddd	RD /= 100				4
DUPLR     RD		000101 1101 111 ddd	RD = (RD & 0xFF) | (RD << 8)
FPMULD@@  RMS,RMD	000101 1110 sss ddd	[RMD] *= [RMS]				4, 20
FPIMULD@@ RMS,RMD	000101 1111 sss ddd	[RMD] *= [RMS]				5, 20
MVO@      R0,RS		000110 0000 000 sss	[R0] = RS
MVI@      R0,RD		000110 0000 001 ddd	RD = [R0]
ADD@      R0,RD		000110 0000 010 ddd	RD += [R0]
SUB@      R0,RD		000110 0000 011 ddd	RD -= [R0]
CMP@      R0,RD		000110 0000 100 ddd	set_flags(RD - [R0])
AND@      R0,RD		000110 0000 101 ddd	RD &= [R0]
XOR@      R0,RD		000110 0000 110 ddd	RD ^= [R0]
MVOC@     R0,RS		000110 0000 111 sss	[R0] = ~RS
MVON@     R0,RS		000110 0001 000 sss	[R0] = -RS
MVI@      R0+RD,RD	000110 0001 001 ddd	RD = [R0 + RD]
MVI@      R0+2*RD,RD	000110 0001 010 ddd	RD = [R0 + 2 * RD]
ABSR      RD		000110 0001 011 ddd	RD = |RD|
NABSR     RD		000110 0001 100 ddd	RD = -|RD|
POW2R     RD		000110 0001 101 ddd	RD = 1 << RD				25
SGNR      RD		001010 0001 110 ddd	RD = sign(RD)				5, 26
ABSD@     RMD		000110 0001 111 ddd	[RMD] = |[RMD]|				5, 20
OR        ADDR, RD	000110 0010 000 ddd	RD |= [ADDR]				27
ANDN      ADDR, RD	000110 0010 001 ddd	RD &= ~[ADDR]				27
XORN      ADDR, RD	000110 0010 010 ddd	RD ^= ~[ADDR]				27
ORN       ADDR, RD	000110 0010 011 ddd	RD |= ~[ADDR]				27
NAND      ADDR, RD	000110 0010 100 ddd	RD = ~(RD & [ADDR])			27
XNOR      ADDR, RD	000110 0010 101 ddd	RD = ~(RD ^ [ADDR])			27
NOR       ADDR, RD	000110 0010 110 ddd	RD = ~(RD | [ADDR])			27
TST       ADDR, RD	000110 0010 111 ddd	set_flags(RD & [ADDR])			27
XCHG      ADDR, RD	000110 0011 000 ddd	RD <--> [ADDR]				27
ADC       ADDR, RD	000110 0011 001 ddd	RD += [ADDR] + C			27
SBC       ADDR, RD	000110 0011 010 ddd	RD -= ([ADDR] + ~C)			27
SLL       RD,ADDR	000110 0011 011 ddd	RD <<= [ADDR]				27
SLR       RD,ADDR	000110 0011 100 ddd	RD >>= [ADDR]				27
SAR       RD,ADDR	000110 0011 101 ddd	RD >>>= [ADDR]				27
ROL       RD,ADDR	000110 0011 110 ddd	RD rol= [ADDR]				27
ROR       RD,ADDR	000110 0011 111 ddd	RD ror= [ADDR]				27
MUL       ADDR,RD	000110 0100 000 ddd	RD *= [ADDR]				4, 27
IMUL      ADDR,RD	000110 0100 001 ddd	RD *= [ADDR]				5, 27
DIV       ADDR,RD	000110 0100 010 ddd	RD /= [ADDR]				4, 27
IDIV      ADDR,RD	000110 0100 011 ddd	RD /= [ADDR]				5, 27
REM       ADDR,RD	000110 0100 100 ddd	RD = RD % [ADDR]			4, 27
IREM      ADDR,RD	000110 0100 101 ddd	RD = RD % [ADDR]			5, 27
FPMULD@@  ADDR,RMD	000110 0100 110 ddd	[RMD] *= [ADDR]				4, 27, 28
FPIMULD@@ ADDR,RMD	000110 0100 111 ddd	[RMD] *= [ADDR]				5, 27, 28
VMOV@@    ADDR,RMD	000110 0101 000 ddd	v3d[RMD] = v3d[ADDR]			18, 27
DADD@@    ADDR,RMD	000110 0101 001 ddd	[RMD] += [ADDR]				20, 27
DSUB@@    ADDR,RMD	000110 0101 010 ddd	[RMD] -= [ADDR]				20, 27
LOOPE     RD,dest	000110 0101 011 ddd	RD--; R7 += disp16 if RD!=0 & Z=1	19
BREVR     R0		000110 0101 011 110	R0 = bit_reverse(R0)
BREVR     R1		000110 0101 011 111	R1 = bit_reverse(R1)
LOOPNE    RD,dest	000110 0101 100 ddd	RD--; R7 += disp16 if RD!=0 & Z=0	19
BREVR     R2		000110 0101 100 110	R2 = bit_reverse(R2)
BREVR     R3		000110 0101 100 111	R3 = bit_reverse(R3)
LOOPS     RD,dest	000110 0101 101 ddd	RD--; R7 += disp16 if RD!=0 & S=1	19
BREVR     R4		000110 0101 101 110	R4 = bit_reverse(R4)
BREVR     R5		000110 0101 101 111	R5 = bit_reverse(R5)
LOOPNS    RD,dest	000110 0101 110 ddd	RD--; R7 += disp16 if RD!=0 & S=0	19
COMC			000110 0101 110 110	C = !C
ENAEXT			000110 0101 110 111	enable_extended_opcodes			29
DBTR      RD		000110 0101 111 ddd	RD = double_bits(RD)			30
REV4R     RD		000110 0110 000 ddd	RD = RD[3:0][7:4][11:8][15:12]		31
REV4HR    RD		000110 0110 001 ddd	RD = RD[11:8][15:12][3:0][7:4]		32
FPINVD@   RMD		000110 0110 010 ddd	[RMD] = 1 / [RMD]			4, 28
MVOIA     DATA, ADDR	000110 0110 011 000	[ADDR] = DATA				33
ADDIA     DATA, ADDR	000110 0110 011 001	[ADDR] += DATA				33
SUBIA     DATA, ADDR	000110 0110 011 010	[ADDR] -= DATA				33
CMPIA     DATA, ADDR	000110 0110 011 011	set_flags([ADDR] - DATA)		33
ANDIA     DATA, ADDR	000110 0110 011 100	[ADDR] &= DATA				33
XORIA     DATA, ADDR	000110 0110 011 101	[ADDR] ^= DATA				33
ORIA      DATA, ADDR	000110 0110 011 110	[ADDR] |= DATA				33
ANDNIA    DATA, ADDR	000110 0110 011 111	[ADDR] &= ~DATA				33
XORNIA    DATA, ADDR	000110 0110 100 000	[ADDR] ^= ~DATA				33
ORNIA     DATA, ADDR	000110 0110 100 001	[ADDR] |= ~DATA				33
NANDIA    DATA, ADDR	000110 0110 100 010	[ADDR] = ~([ADDR] & DATA)		33
XNORIA    DATA, ADDR	000110 0110 100 011	[ADDR] = ~([ADDR] ^ DATA)		33
NORIA     DATA, ADDR	000110 0110 100 100	[ADDR] = ~([ADDR] | DATA)		33
TSTIA     DATA, ADDR	000110 0110 100 101	set_flags([ADDR] & DATA)		33
XCHGIA    DATA, ADDR	000110 0110 100 110	[ADDR] <--> DATA			33, 34
ADCIA     DATA, ADDR	000110 0110 100 111	[ADDR] += DATA + C			33
SBCIA     DATA, ADDR	000110 0110 101 000	[ADDR] -= (DATA + ~C)			33
SLLIA     DATA, ADDR	000110 0110 101 001	[ADDR] <<= DATA				33
SLRIA     DATA, ADDR	000110 0110 101 010	[ADDR] >>= DATA				33
SARIA     DATA, ADDR	000110 0110 101 011	[ADDR] >>>= DATA			33
ROLIA     DATA, ADDR	000110 0110 101 100	[ADDR] rol= DATA			33
RORIA     DATA, ADDR	000110 0110 101 101	[ADDR] ror= DATA			33
MULIA     DATA, ADDR	000110 0110 101 110	[ADDR] *= DATA				4, 33
IMULIA    DATA, ADDR	000110 0110 101 111	[ADDR] *= DATA				5, 33
DIVIA     DATA, ADDR	000110 0110 110 000	[ADDR] /= DATA				4, 33
IDIVIA    DATA, ADDR	000110 0110 110 001	[ADDR] /= DATA				5, 33
REMIA     DATA, ADDR	000110 0110 110 010	[ADDR] = [ADDR] % DATA			4, 33
IREMIA    DATA, ADDR	000110 0110 110 011	[ADDR] = [ADDR] % DATA			5, 33
SWAP      RD		000110 0110 110 1dd	swap_bytes(RD)				35
STCP      RD		000110 0110 111 ddd	C = parity(RD)				36
DISEXT			000110 0110 111 111	disable_extended_opcodes		29
POW10RL   RD		000110 0111 000 ddd	RD = low_word(pow(10,RD))		37
POW10RH   RD		000110 0111 001 ddd	RD = high_word(pow(10,RD))		37
FPISQRTR  RD		000110 0111 010 ddd	RD = 1 / sqrt(RD)			4, 9, 38
FPLNR     RS,RD		000110 0111 011 ddd	RD = ln(RD)				4, 9
FPEXPR    RS,RD		000110 0111 100 ddd	RD = exp(RD)				5, 9
FPSINR    RS,RD		000110 0111 101 ddd	RD = sin(RD)				5, 9, 40
FPCOSR    RS,RD		000110 0111 110 ddd	RD = cos(RD)				5, 9, 40
FPIINVD@  RMD		000110 0111 111 ddd	[RMD] = 1 / [RMD]			5, 28
FPATAN2R  RS,RD		000110 1000 sss ddd	RD = atan2(RS,RD)			5, 9, 39



Notes
-----

1.  If xxx is 0, uses direct addressing instead (@R0 is not supported).
2.  @R0 is supported.  Direct addressing is handled by a different opcode.
3.  Src is not altered.  Auto-increment for SDBD purposes arises from RD
    (Src is the base address, RD is the index address).
4.  Operands are treated as unsigned.
5.  Operands are treated as signed.
6.  m should have no effect
7.  Changes the low byte only, leaving the high byte unaltered.
8.  aaa is always different from bbb
9.  Operands are treated as 16-bit fixed-point numbers in 8.8 format.
10. Produces a 32-bit result with the high word placed in R1 and the low word placed in R0.
11. Unpacks the two bytes in RA into RA and RB.
12. Packs the low bytes of RA and RB into RA.
13. RD <-- hexadecimal ASCII representation of the low byte of RD (e.g. 0x000A --> 3041 "0A")
14. Shifts bits from R0 into RD.  R0 is unaltered.  RD may be in the range R1..R3.
15. RD = binary value (0..255) of hexadecimal ASCII characters stored in RD.  Invalid
    characters in a byte result in that byte being interpreted as 0 (e.g. 3041 --> 0x0A,
    2F41 --> 0x0A). Ignores case.
16. Shifts bits from RS into R0. RS is unaltered. C = low bit of R0 shifted out if a > 0.
    RS may be in the range R1..R3.
17. Does ***not*** change RM if mmm>3. Supports SDBD.
18. Copies a 3-vector from [Src] to [RMD].  Each vector component is 32 bits, for a total
    copy of 6 words.
19. ddd < 6
20. Operands are 32 bits in size.
21. RD = number of consecutive 0 bits in RD starting at the MSB
22. RD = number of consecutive 1 bits in RD starting at the MSB
23. RD = number of consecutive 0 bits in RD starting at the LSB
24. RD = number of consecutive 1 bits in RD starting at the LSB
25. If RD > 15, result is 0.
26. Result is either -1, 0, or 1.
27. Direct addressing mode version.
28. Operands are treated as 32-bit fixed-point values in 16.16 format.
29. No effect in the emulator (extended opcodes are always active).  Reserved for a
    physical CPU.
30. RD = doubled bits of low byte of RD (e.g. 0x0011 --> 0x0303)
31. Reverses the order of the 4-bit nibbles in RD (e.g. 0x0123 --> 0x3120).
32. Reverses the order of the 4-bit nibbles in each byte of RD (e.g. 0x0123 --> 0x1032).
33. Three-word instruction: the second word is an address and the third word is an immediate
    value.  SDBD is not supported.
34. If running from ROM, net effect is [ADDR] = DATA.
35. RD is indexed by dd + 4, i.e. RD is in the range R4..R7.
36. ddd <> 7.  If RD contains an odd number of 1 bits, C = 1, else C = 0 (sets carry as RD parity)
37. If RD > 9, the result is 0.
38. Uses fast-inverse-square-root approximation algorithm with one iteration.
39. RS is the X value and RD is the Y value.  Result is in radians and is accurate to 0.01 radians.
40. RD must be expressed in radians in the range -2*pi .. 2*pi.  Result might be off by 1/256 (the LSB).

 

Edited by JohnPCAE
Link to comment
Share on other sites

I found a block of mistakes in my specification posted above. The section in question should read like this:

 

SLLR      RD,RA		000011 1100 aaa ddd	RD <<= RA
SLRR      RD,RA		000011 1101 aaa ddd	RD >>= RA
SARR      RD,RA		000011 1110 aaa ddd	RD >>>= RA
ROLR      RD,RA		000011 1111 aaa ddd	RD rol= RA
RORR      RD,RA		000100 0000 aaa ddd	RD ror= RA
MULR      RS,RD		000100 0001 sss ddd	RD *= RS				4
IMULR     RS,RD		000100 0010 sss ddd	RD *= RS				5
DIVR      RS,RD		000100 0011 sss ddd	RD /= RS				4
IDIVR     RS,RD		000100 0100 sss ddd	RD /= RS				5
REMR      RS,RD		000100 0101 sss ddd	RD = RD % RS				4
IREMR     RS,RD		000100 0110 sss ddd	RD = RD % RS				5
.
.
.
MVOD@     RS,RM+disp16	000101 1000 mmm sss	[RM + disp16] = RS			17

 

Edited by JohnPCAE
Link to comment
Share on other sites

I haven't the slightest idea where the RAM space came from, but I managed to squeeze in a few extra instructions at the end (see below). Most are intended to ease blitting sprites to the screen in various graphics modes. The last two instructions were added just to fill out the opcode block. They could possibly be used for precise time measurement.

 

Testing is going well. I greatly simplified the emulator code with C macros to make the testing space much smaller. I'm almost at the point where I just have to build and validate the final hardware design before posting everything.

 

MVONZx    RS, dst	000110 1010 xxx sss	If RS <> 0, [dst] = RS
BLIT4@    RS, RM	000110 1011 00m sss	blit_with_transparency(RS -> [RM])	42
BLIT16@   RS, RM	000110 1011 01m sss	blit_with_transparency(RS -> [RM])	43
BLIT256@  RS, RM	000110 1011 10m sss	blit_with_transparency(RS -> [RM])	44
MVONZ@    RS, R0	000110 1011 110 sss	If RS <> 0, [R0] = RS
BREVBR    RD		000110 1011 111 ddd	RD = bit_reverse_bytes(RD)		45
RUNCLR			000110 1011 111 110	R0 = low word of cycle counter
RUNCHR			000110 1011 111 111	R0 = high word of cycle counter

42. RM must be R4 or R5.  Pairs of bits are written from RS to [RM] if they are not 00.
43. RM must be R4 or R5.  Sets of 4 bits are written from RS to [RM] if they are not 0000.
44. RM must be R4 or R5.  Bytes are written from RS to [RM] if they are not 0.
45. ddd < 6.  Reverses the bits of individual bytes in RD.

 

  • Like 1
Link to comment
Share on other sites

I've been doing lots of testing of the emulation engine and I wound up running into problems with certain kinds of instructions not having enough time to run, so I looked into the possibility of overclocking the Pico. It turns out that people have been overclocking the heck out of it and someone went so far as to plot what speeds it can achieve, at what internal core voltage, and what its internal temperature reaches. Long story short, ramping it up to 155MHz is just enough to solve my speed issues and the internal temperature goes up by only about 2 degrees F (so we're talking basically 70 to 72 degrees F, still room temperature). It turns out that the reason for the Pico's advertised maximum speed of 133MHz is due to the rating of its flash chip (which at any rate can handle far higher speeds).

 

I can't run from flash because of its latency and so everything needs to run from the Pico's internal RAM which doesn't suffer from such limitations, and it turns out that the Pico can run at 155MHz standing on its head according to the data. This is a good thing not only because it solves the speed issues but also means that a PAL version might be possible in the future. It would have to run at 166MHz to keep up with the 17MHz PAL color frequency, which would add another degree or two Fahrenheit to its temperature, but according to the data even clocked up to 420MHz (!) it only reaches a temperature of 40C. So things are looking much better for a potential PAL version. I'm tempted to just run it at 166MHz now to standardize the code for synchronizing with the Intellivision bus. I suppose one could use the power LED header on my mainboard to connect a tiny fan, but from everything I've seen it's entirely unnecessary, especially since my design suspends the Pico such that there's an air gap below it.

 

A PAL version of my circuit board would require changes to how it counts scan lines since there are more than 256 on a PAL screen and I haven't even looked into how to do that, but at least it seems possible from the standpoint of the software in the Pico. Of course I don't even have any PAL equipment, but that's a bridge to be crossed at another time.

 

EDIT: I recalibrated for 166MHz and it's running like a champ, and the CPU is stone-cold, so I'll probably just leave it there. That way a PAL version would only require recoding of the output routines to duplicate certain scanlines and reverse the color phases (if I understand PAL correctly, correct me if I'm wrong!)

Edited by JohnPCAE
  • Like 1
Link to comment
Share on other sites

Testing, testing, and more testing, and some bug-fixing. I managed to squeeze in just a few more instructions:

 

BLIT2A@   RS, RM	000110 1100 00m sss	[RM] |= RS				46
BLIT4A@   RS, RM	000110 1100 01m sss	blit_with_transparency(RS -> [RM])	46
BLIT16A@  RS, RM	000110 1100 10m sss	blit_with_transparency(RS -> [RM])	46
BLIT256A@ RS, RM	000110 1100 11m sss	blit_with_transparency(RS -> [RM])	46

46. Adds a 16-bit immediate to RM after auto-incrementing it.  Net result is RM = RM + 1 + imm16.

The new instructions are meant to make blitting easier. It lets you blit to a buffer and automatically add the buffer pitch to the destination register so that it's positioned at the right position on the next scan line.

 

I also slightly altered the VMOV@@ instruction. It copies 16 bytes instead of 12, and it requires that the source and destination addresses be 0xFFF8 or less. That is, it doesn't handle address wrapping. If either address is higher than the limit it will do nothing.

 

Also, I've put together the BOM for the two boards. The complete system consists of a small board that plugs into the cartridge port, and the mainboard. A short ribbon cable connects the two.

 

============================
CARTRIDGE BOARD PARTS LIST
============================

Part       Value          Close part #                 Description/important features
-------------------------------------------------------------------------------------------
C1         22pF           C315C220F3G5TA               Ceramic capacitor, 1%, 2.54mm lead spacing
C2         33pf           C315C330F3G5TA               Ceramic capacitor, 1%, 2.54mm lead spacing
C3         100nF          FG18C0G1H103JNT06            MLCC capacitor, 2.54mm lead spacing
C4         33pf           C315C330F3G5TA               Ceramic capacitor, 1%, 2.54mm lead spacing
C5         100nF          FG18C0G1H103JNT06            MLCC capacitor, 2.54mm lead spacing
C6         100nF          FG18C0G1H103JNT06            MLCC capacitor, 2.54mm lead spacing
C7         10pF           C316C100F3G5TA               Ceramic capacitor, 1%, 2.54mm lead spacing
D1         1N715          TZX11B-TR                    Zener diode
FB1        2743002112     4211R-11                     Through-hole ferrite Bead, 8mm length, 135 ohm
IC1        CD74HCT7046A   CD74HCT7046AEE4              Phase-Locked Loop with VCO and Lock Detector
IC2        AD8031N        AD8031ANZ                    Op-amp
IC3        74LS74N        SN74HCT74NE4                 Dual D type positive edge triggered FLIP FLOP, preset and clear
IC4        MAX913CPA      MAX913CPA+                   Voltage comparator
JP1        2x22           70246-4402                   2x22 shrouded, keyed male pin header
R1         10k            MFR-25FRF52-10K              Resistor, 1/4W, 1%, 6.3mm length
R2         10k            MFR-25FRF52-10K              Resistor, 1/4W, 1%, 6.3mm length
R3         10k            MFR-25FRF52-10K              Resistor, 1/4W, 1%, 6.3mm length
R5         33             MFR-25FRF52-33R              Resistor, 1/4W, 1%, 6.3mm length
R6         10k            MFR-25FRF52-10K              Resistor, 1/4W, 1%, 6.3mm length
R7         47k            MFR-25FBF52-47K              Resistor, 1/4W, 1%, 6.3mm length
R8         10k            MFR-25FRF52-10K              Resistor, 1/4W, 1%, 6.3mm length
R9         22k            MFR-25FTF52-22K              Resistor, 1/4W, 1%, 6.3mm length
R10        10k            MFR-25FRF52-10K              Resistor, 1/4W, 1%, 6.3mm length
R11        5.6k           MFR-25FTE52-5K6              Resistor, 1/4W, 1%, 6.3mm length
CABLE      2x22 IDC       IDSD-22-D-03.00-T            2x22 IDC ribbon cable connecting the two boards


Cartridge board notes
-------------------------
1. My IDC ribbon cable is 3" long and keyed.  A 2" cable would probably be ideal but it wasn't available.
   Bear in mind that a keyed cable requires keyed receptacles.

2. The cartridge board serves a very important function: it quadruples the rate of the Intellivision's
   MCLK signal while keeping the result phase-locked.  It passes the result along to the mainboard via
   pin 16.  The incoming MCLK signal from the Intellivision is highly attenuated, and it's important to
   use parts that are in spec for this board to do its job.  Recommend that all passives have a 1%
   tolerance.

3. While it might be tempting to use sockets for the IC's, if they are socketed then a plastic shroud will
   likely not fit around the board.

4. The 100nF capacitors are exactly the same as the ones on the mainboard.  Their sole use is noise
   filtering.

5. The ferrite bead is the same as the ones on the mainboard.  See the mainboard notes for more info on
   the ferrite beads.

6. All capacitors should have 0.1" (2.54mm) lead spacing.

7. The rating of the zener diode is not critical.  I used a 1N715 which is rated for 11V.  The point of
   the diode is only to cut down on ringing.




============================
MAINBOARD PARTS LIST
============================

Part       Value          Close part #                 Description/important features
-------------------------------------------------------------------------------------------
C1..C31    100nF          FG18C0G1H103JNT06            MLCC capacitor, 2.54mm lead spacing (total qty. 30: there is no C20)
CN1                       151-7620E-E                  DC barrel jack, 2mm I.D., 6.3mm O.D.
FB1        2743002112     4211R-11                     Through-hole ferrite Bead, 8mm length, 135 ohm
FB2        2743002112     4211R-11                     Through-hole ferrite Bead, 8mm length, 135 ohm
SOCKET     Preci-Dip      540-88-032-24-008            PLCC-32 socket for 1k FIFO
IC1        7202J          7202LA50JG                   1k x 9 Asynchronous FIFO, 5V
IC2        74LS04N        SN74HCT04NE4                 Hex INVERTER
IC3        74AS574N       SN74HCT574NE4                8-bit D type FLIP FLOP bus driver
IC4        74AS574N       SN74HCT574NE4                8-bit D type FLIP FLOP bus driver
IC5        74LS245N       SN74HCT245NE4                Octal BUS TRANSCEIVER, 3-state
IC6        74LS245N       SN74HCT245NE4                Octal BUS TRANSCEIVER, 3-state
IC7        74LS08N        SN74LS08NE4                  Quad 2-input AND gate, 5V
IC8        74LS245N       SN74HCT245NE4                Octal BUS TRANSCEIVER, 3-state
IC9        CD74HC40103    CD74HC40103EE4               High-Speed CMOS Logic 8-Stage Synchronous Down Counter
IC10       74LS08N        SN74LS08NE4                  Quad 2-input AND gate, 5V
IC11       74LS08N        SN74LS08NE4                  Quad 2-input AND gate, 5V
IC12       CD74HC40103    CD74HC40103EE4               High-Speed CMOS Logic 8-Stage Synchronous Down Counter
IC13       CD74HC40103    CD74HC40103EE4               High-Speed CMOS Logic 8-Stage Synchronous Down Counter
IC14       CD74HC40103    CD74HC40103EE4               High-Speed CMOS Logic 8-Stage Synchronous Down Counter
IC15       74ALS73AN      SN74LS73AN                   Dual J-K FLIP FLOP, clear
IC16       74LS04N        SN74HCT04NE4                 Hex INVERTER
IC17       74AS574N       SN74HCT574NE4                8-bit D type FLIP FLOP bus driver
IC18       74ALS73AN      SN74LS73AN                   Dual J-K FLIP FLOP, clear
IC19       CD74HCT4520N   CD4520BEE4                   Dual syncronous binary UP-COUNTER
IC20       74LS245N       SN74HCT245NE4                Octal BUS TRANSCEIVER, 3-state
IC21       74LS04N        SN74HCT04NE4                 Hex INVERTER
IC22       74LS08N        SN74LS08NE4                  Quad 2-input AND gate, 5V
IC23       74LS08N        SN74LS08NE4                  Quad 2-input AND gate, 5V
IC24       74ALS73AN      SN74LS73AN                   Dual J-K FLIP FLOP, clear
IC25       74AS574N       SN74HCT574NE4                8-bit D type FLIP FLOP bus driver
IC26       74LVC245N      SN74LVC245ANE4               LOW-VOLTAGE Octal BUS TRANSCEIVER, 3-state
IC27       74LVC245N      SN74LVC245ANE4               LOW-VOLTAGE Octal BUS TRANSCEIVER, 3-state
IC28       74LVC245N      SN74LVC245ANE4               LOW-VOLTAGE Octal BUS TRANSCEIVER, 3-state
IC29       74LVC245N      SN74LVC245ANE4               LOW-VOLTAGE Octal BUS TRANSCEIVER, 3-state
IC30       74AS574N       SN74HCT574NE4                8-bit D type FLIP FLOP bus driver
IC31       74LS00N        SN74HCT00N                   Quad 2-input NAND gate
JP1        1x20           929850-01-20-RB              1x20 female pin header
JP2        1x20           929850-01-20-RB              1x20 female pin header
JP3        2x6            929852-01-06-RA              2x6 female pin header
JP4        2x22           70246-4402                   2x22 shrouded, keyed male pin header
JP5/JP6    2x22           392-044-558-201              Cartridge edge connector
JP7        1x2            171856-0102                  1X02 male pin header (for optional power LED)
PB1        PUSHBUTTON_6MM SKHLABA010                   Small 2-contact pushbutton (Adafruit sells them in packets of 20)
PWRSUPP    SKM10E-05      SKM10E-05                    MEAN WELL 5V 2A DC-DC Power Converter
Q1         IRF4905        IRF4905PBF                   TO220BH P-Channel HEXFET® Power MOSFET
R1         1M             MFR-25FTE52-1M               Resistor, 1/4W, 1%, 6.3mm length
R2         40k            MFR-12FTF52-40K              Resistor, 1/6W, 1%, 6.3mm length
R3         20k            MFR-25FBF52-20K              Resistor, 1/4W, 1%, 6.3mm length
R4         10k            MFR-25FRF52-10K              Resistor, 1/4W, 1%, 6.3mm length
R5         5k             MFR-25FTE52-4K99             Resistor, 1/4W, 1%, 6.3mm length
R6         2.5k           MFR-25FBF52-2K49             Resistor, 1/4W, 1%, 6.3mm length
R7         1.25k          MFR-25FBF52-1K24             Resistor, 1/4W, 1%, 6.3mm length
R8         625            MFR-25FRF52-620R             Resistor, 1/4W, 1%, 6.3mm length
R9         312            MFR-25FRF52-309R             Resistor, 1/4W, 1%, 6.3mm length
R10        3.9k           MFR-25FBF52-3K9              Resistor, 1/4W, 1%, 6.3mm length
R11        1k             MFR-25FRE52-1K               Resistor, 1/4W, 1%, 6.3mm length
R12        470            MFR-25FTE52-470R             Resistor, 1/4W, 1%, 6.3mm length
R13        820            MFR-25FBF52-820R             Resistor, 1/4W, 1%, 6.3mm length
R14        820            MFR-25FBF52-820R             Resistor, 1/4W, 1%, 6.3mm length
R15        1k             MFR-25FRE52-1K               Resistor, 1/4W, 1%, 6.3mm length
R16        1k             MFR-25FRE52-1K               Resistor, 1/4W, 1%, 6.3mm length
R17        1k             MFR-25FRE52-1K               Resistor, 1/4W, 1%, 6.3mm length
X1         DSUB25-F       09663526611                  Female D-Sub-25 right-angle parallel port connector


Mainboard notes
-------------------------
1.  For resistors, any 1/4W 1% tolerance resistor that's 6.3mm or less will do.  It's okay to use a 1/6W
    resistor for the 40k one as it's only in the resistor ladder for the output video.

2.  For the 1M resistor, the board will accommodate a larger 1/2W one but it isn't necessary.

3.  All capacitors are the same, 100nF, with 0.1" (2.54mm) lead spacing.

4.  For chips, generally speaking, try to remain compatible with TTL logic levels if possible.

5.  It is ***CRITICAL*** to use LVC (low-voltage) variants for IC26-IC29.  They translate 5V logic levels
    to 3.3V for the Raspberry Pi Pico.  Not using LVC chips absolutely WILL fry either the Pico or IC26-IC29.

6.  The MEAN WELL switching power supply has an upper limit of 9 volts input.  Recommended DC power supply
    is 6V 2A.  The barrel jack from the wall-wart power supply must be center-positive.

7.  The hardest part to acquire by far is the cartridge connector.

8.  PB1 is a reset button for the Raspberry Pi Pico.  It isn't strictly necessary.

9.  JP7 is a locking header for an optional power LED.

10. JP3 is a header for possible expansion.  It provides the digital video levels just before they are
    converted to analog.  A potential use is conversion to DVI/HDMI.

11. The ferrite beads I have are Fair-Rite 2743002112 through-hole axial beads, with an approximate
    length of 8mm and 135-ohm impedance.  The impedance value was not specifically chosen, it's just
    what looked okay and they do a good (and important) job of removing noise from the power rails.
    Try to use something similar in size and impedance.

12. Recommend using sockets for all chips.  It's cheap insurance.

13. You also need a Raspberry Pi Pico and headers for it, of course. It plugs into JP1 and JP2.
    DO NOT use its castellated holes to solder it directly to the mainboard or (a) its ability to cool
    itself will suffer, (b) you won't be able to plug your USB cable into it to load the software,
    and (c) it will probably short against the vias under it.

The (almost certainly) final versions of the boards are on their way to me, so once I receive them I'll assemble and validate them. They're only slightly tweaked from what I have now so I don't expect any problems. At that point I should be about ready to release everything. I'm planning on GPL'ing all of the code because of what artrag went through. As for the board designs, my plan is to release them in both Eagle and Gerber formats.

Edited by JohnPCAE
Link to comment
Share on other sites

I really hate how Mouser lists capacitors. I accidentally chose 10nF capacitors instead of 100nF ones from their parts list, so the part shown in my BOM is incorrect. Attached is the correct BOM.

 

BOM.txt

 

I'm just about finished with software testing. I can't exhaustively test every single possible opcode but I've tested all of the emulated instructions and I've tested each of the addressing modes many times in the process. I'm glad I did all this testing because it wound up showing many little bugs in the emulator. I think the last part of the software to test is some of the high-level configuration stuff. The boards haven't arrived yet anyway so I have some time.

 

There's been a minor change to the opcode layout. I realized that TSTR and XCHR are symmetric and require only half of the opcodes they were actually using, so I managed to condense them into a smaller layout. This freed up a block of opcodes that I was able to use for a new instruction, AND@@. It takes the form AND@@  RMS, RMD. It reads one word at the addresses referenced by each of two registers, ANDs them together, and writes the result to [RMD]. Its main benefit would be to rapidly AND a mask into a buffer where either or both of the addresses would auto-increment. It doesn't support SDBD: there just isn't enough RAM space left for the code to do it.

 

So the resulting opcode encoding in the affected region now looks like this:

 

INCLR     RD		000011 0111 ddd ddd	lowbyte(RD)++
AND@@     RMS, RMD      000011 0111 sss ddd     [RMD] &= [RMS]
TSTR      RA, RB	000011 1000 aaa bbb	set_flags(RA & RB)
DECLR     RD		000011 1000 ddd ddd	lowbyte(RD)--
XCHGR     RA, RB	000011 1000 aaa bbb	RA <--> RB
  
- for AND@@, sss is never equal to ddd.
- for TSTR, aaa is always less than bbb.
- for XCHGR, aaa is always greater than bbb.

 

 

Edited by JohnPCAE
Link to comment
Share on other sites

Major feature update

 

For a long while there has been a feature that I wanted to add as soon as I put in sprite exclusion. Having the Pico overclocked to 166MHz enabled me to condense some emulated instruction code, which in turn allowed me to free up the RAM space necessary for the code to do it.

 

What feature? When I showed sprite exclusion I mentioned that it would be easy to extend it to blit sprites instead of just masking out areas where sprites were displayed. And now it's reality.

 

The picture below shows what it can do. At the top it's excluding 8 sprites that would represent the STIC's actual sprites. And below that it's blitting an additional 248 sprites of its own. Basically I extended the subsystem to handle up to 256 sprites, where the first 8 are exclusion-only and the rest it will blit on its own with colors that you designate.

 

sprites.thumb.png.b702aaf6f280293b1dd22093514b0e7a.png

 

There are some caveats.

 

Sprites that are flipped or are clipped on the edges of the screen require a tiny bit more processing, and stretched sprites require significantly more CPU time since it has to push many more pixels to the screen. That said, for the normal-size running man sprites shown here, it can handle all 256 sprites in every bitmap-graphics screen mode that allows sprite exclusion. As another example, it can handle 256 horizontally-stretched, non-clipped sprites in 16-color mode. Generally speaking, the number of sprites it can display depends on the screen mode and their size. In general this is only viable in bitmap graphics modes, though you might be able to display a sprite or two in text mode. The reason is that when in text mode, it first has to convert the display to a bitmap which takes a significant amount of time.

 

There is NO sprite collision checking. That would require a Pico that's maybe ten times as fast as this one, with vastly more RAM than it has. That's something you'll have to handle with the CPU, either the real one or the emulated one.

 

The second image shows what happens when you ask it to do too much. It's trying to handle 256 double-width sprites in 16-bit true-color mode. The Pico can't get all that done before it has to output scan lines to the screen, so the output gets delayed. It can handle that in 160x191x16 mode because that requires a lot less data to be moved around.

 

sprites_too_much_work.thumb.png.ae0e04521d85eaeba70d505d672504f6.png

 

So, who wants to volunteer to code the Robotron port?

 

Edited by JohnPCAE
  • Like 1
Link to comment
Share on other sites

I should point out that the sprites don't have to all be the same size. You can mix and match exactly the way you can with the STIC. Each sprite has an attribute byte that lets you set visibility, X flip, Y flip, X stretch, Y stretch, and Y double-stretch. They get rendered from 255 down to 0, with the final eight sprites being the exclusion ones (think about it -- they have to be on top). There is also no limit on how many sprites can be displayed on a line, since it's rendering to an offscreen buffer before writing scan lines out to the hardware. It doesn't care where sprites are.

 

I should also point out that since you're free to paint a sprite with black, you can use any non-exclusion sprite as an exclusion sprite. So, for instance, if you want some cards that the STIC is displaying to be shown on top, just use a sprite with the color set to black to exclude whatever pixels you like, and use the lowest-numbered sprites as your extra exclusion ones since they get drawn last.

 

Why are the first 8 sprites special in that they are exclusion-only? SPEED. It's faster to only use a sprite for exclusion than to also paint in a color.  Since it takes so long to convert a text-mode screen into a bitmap, if you want to exclude *any* sprites in text mode the Pico needs all the help it can get. So for sprites 0-7 the Pico uses special exclusion-only code instead of the full sprite-painting code. Only sprites 8-255 get the full treatment.

Edited by JohnPCAE
  • Like 1
Link to comment
Share on other sites

Wow. I stand corrected on what this can do in 40-column text mode. Shown is the software excluding all 8 Intellivision sprites at normal size and then displaying 144 sprites of its own (about the most it can handle if none of them are clipped). When the Pico was running at 133MHz it could barely exclude a single sprite, but at 166MHz it can do all this. Nice.

 

As a reminder, sprite exclusion in text mode, as opposed to bitmap graphics mode, involves an extra step of rendering the text to a bitmap before it can perform sprite exclusion. This limits how many sprites it can handle since it has to do all this every frame between when SR1 from the Intellivision pulses low and when it has to output scan lines to the hardware.

 

I received my updated cartridge boards yesterday, but I'm still waiting on the mainboards as well as components. In the meantime I'm polishing the source code.

 

sprites_144_text_mode.thumb.png.1b8328b02b9951cbf41e5929e2d6de29.png

  • Like 2
Link to comment
Share on other sites

Some more eye-candy.

 

Running at 166MHz meant that I don't have to go to crazy-extreme measures to display 80-column text. When it was running at 133MHz, I had to have 256 separate code snippets, one for each of the 256 possible dot patterns in a byte. But running at 166MHz means that I can get away with having only 16 code snippets for a four-bit pattern, and incur the overhead of calling it twice. This saved a boatload of RAM, upwards of 20k. So now all of a sudden I have a bunch of RAM available for more code.

 

This in turn allowed me to write code for sprite exclusion in 80-column mode, with two caveats. First, since it has to convert twice as many characters into a bitmap it can't display as many sprites. The screenshot below shows 80 non-clipped sprites, which is about the most it can handle. The second caveat is that it has to convert the text to a 16-color (4bpp) graphics mode. The reason is there isn't enough buffer space in 128k for the text buffer, a separate bitmap buffer, and the sprite info. So it only looks at the low 4 bits of the foreground and background colors when converting. Note that this is only a factor if you enable sprite exclusion: if you don't turn it on, you have the full 256-color palette available for foreground and background colors in 80-column text mode.

 

I suppose there are multiple potential benefits from using sprite exclusion in a text mode, but for me the main benefit is that you can use it for a hardware cursor that isn't just a text block. You can have an actual arrow instead, albeit a blocky one like an Intellivision sprite.

 

In other news, last night I figured out how to wait long enough in a DTB cycle before I can safely stop outputting data onto the Intellivision bus. It means that I don't have to do it in the following NACT cycle. This frees up the NACT following a DTB that I have to service for running the emulated CPU. So now the emulated CPU can run in all NACT cycles, as well as IAB, DW, and INTAK. Its effective speed relative to the physical CPU will therefore range from 2x to 6x, since all emulated instructions execute in a single one of those aforementioned cycles. And that's not counting the extended instructions that can do things with a single instruction that would take the physical CPU far more to accomplish.

 

sprites_80_80col_text_mode.thumb.png.86b8e9b9905b98eaf23c17b91e38064e.png

Edited by JohnPCAE
  • Like 1
Link to comment
Share on other sites

My circuit boards are all here now, but I spent the day working on the emulated CPU. In the past few days I've added some instructions that produce 32-bit fixed-point results and perform some fixed-point 32-bit arithmetic:

 

FPLND
FPEXPD
FPSIND
FPCOSD
FPDIVD@@
FPIDIVD@@

 

There's also a new FPSQRTR instruction that gives an 8.8 format square root, and new VSTO@ instruction that fills 16 words of memory with the value in a source register. So you can do really fast memory fills as well as really fast memory copies. How fast? I did some quick timing calculations and it can:

 

- copy 8 words 78% as fast as a 16MHz 80386

- fill 16 words 179% as fast as a 16MHz 80386

 

But there's even more. With FPDIVD@@, it takes two 16.16 fixed-point values in memory, divides one by the other, and stores the result. It can do this 115% as fast as a 16MHz 80386, and that's not including the additional shifts that are required to go to and from fixed-point format on the 386 or the operations to load one value from memory and store the result. Bear in mind that all emulated instructions always take 2.235 us to run (i.e. two Intellivision clock cycles), so the more an instruction can do, the more efficient it is.

 

There's method to the madness of putting all these instructions in. Wolfenstein 3D required an 80286 to run (which doesn't have 32-bit instructions). From my timing analysis, the most expensive operations run on par with the fastest 80286's ever made and close to the first 80386 CPU's. It makes me wonder if a complete port of Wolfenstein 3D to the Inty will be possible. I've been trying to make it so, at least.

Edited by JohnPCAE
Link to comment
Share on other sites

I've made a small update to the BOM. The Zener diode should be a 1N751, not a 1N715. It's rated for 5.1V. The rating is probably important. Updated file attached.

 

I just finished building the final version of the cartridge board and it's working correctly. The next step is to build the final version of the mainboard. I'll probably have to order some components first.

 

The software is packed to the gills and I'm not sure that I can add any more to it. I managed to squeeze in basic single-precision floating-point support (add, subtract, multiply, divide, square root, abs, neg, etc. and several conversion opcodes). Floating-point support is really hard to get to run within the time budget but so far so good (for add and subtract I had to split them into two instructions because of the time it takes to renormalize the result, so first you do an FADD/FSUB and then you do an FOUT to normalize and output the result). I've gotten pretty good at Arm Thumb assembly. It just needs some more testing. There are also some goodies for accessing bit-packed arrays, which should be a help since space in the Inty is always at a premium. Those aren't tested yet.

 

 

BOM.txt

Edited by JohnPCAE
Link to comment
Share on other sites

I'm still waiting on parts before I can finish building the final mainboard and start testing it. My order from Mouser was supposed to arrive on Friday, but for some reason it didn't leave Dallas until yesterday. And now it's sitting somewhere at their Philly distribution center next to the airport, literally *seven whole miles* from my house, and estimated delivery isn't until Tuesday night.

 

For crying out loud.

 

The software has passed all of my tests so far and I'm about out of ideas as to what to do next to it. There's a tiny bit of available RAM left; maybe I'll see if I can think of a few more emulated instructions to add, or maybe I'll just leave it as-is in case it's needed later. As it stands, the emulated coprocessor has a *lot* of available instructions, far more than when I last posted the opcode list. Porting something like Keyboard Component software to it wouldn't even make it break a sweat.

 

Speaking of which, I've been thinking a lot about its parallel port of late. I was very tempted to pick up an old HP Thinkjet printer on ebay and write some Inty software to print to it, but I've decided on something else. A Raspberry Pi Pico has USB host capability, so a Pico (with appropriate level-shifting IC's and other stuff) plugged into the parallel port could make for an easy way to have an Intellivision talk to various USB devices. So once I release all of the design files and software for this project I think I'll take a stab at it. If nothing else, being able to use modern USB keyboards and mice with an Intellivision could make for some interesting and in-depth games.

 

I also toyed with the idea of breaking out my old parallel port Iomega ZIP drive and trying to talk to that, but I think being able to talk to a USB stick would be a much better solution. I have no idea how far the USB idea can be pushed (maybe a USB wifi device?) but I'll make any software I write public, so any of us will be able to work on it.

Edited by JohnPCAE
Link to comment
Share on other sites

I got my parts today and got to work. The final hardware design has been built and it's working ?

 

I've started working on documentation, but that will be a long process. In the meantime, there's a good chance of a full release sometime tonight for people to start with, so standby. I just want to work on the documentation some more first. It will be incomplete but it will be enough to start with until I can flesh it out more.

Link to comment
Share on other sites

Okay. For better or for worse, it's ready for the larger community to start playing with it. So I bring to you the Advanced Console Component. It includes full hardware designs and Gerber code for making your own circuit boards, a BOM (bill of materials), full GPL'ed code for the Pi Pico, as well as a prebuilt binary (overlay.uf2). It also includes what documentation I've finished so far as well as an example Inty program that does a simple test. Documentation is far from finished, but it's enough to get people started and the example Inty program will help.

 

Everything is of course subject to change as we play with it, but at this point I don't foresee any changes save documentation. If there are any bugs, I'm unaware of them.

 

Note that this is NTSC-only, and works best with an Intellivision II or an original Inty that has had the System Changer mod. That said, it will also work with an unmodified Intellivision, though the overlaid video will be much dimmer. This isn't anything I can control as it's due to the large resistor in the original Intellivision that attenuates incoming video. A System Changer mod is highly recommended. Also, you won't see any output from this on RGB-modded consoles as it provides composite video over the Intellivision's video overlay pin and an RGB mod won't see or process it. It does provide a header so that a future RGB device can pick off its video in digital form, but building one is an exercise for the people who make RGB mods ?

 

Advanced Console Component 20220208.zip

Edited by JohnPCAE
  • Like 2
  • Thanks 1
Link to comment
Share on other sites

Updated release:

 

I've expanded the coprocessor documentation by quite a lot in the past 24 hours, and in the midst of working on it I uncovered a very minor bug in the code (if you ran a JE/JD/JSRE/JSRD instruction, it would enable interrupts when you asked it to disable them, and vice versa). So this update has a new build as well as a much larger document. There's still much more to add to the documentation, but this adds quite a lot. I also made some minor tweaks to a handful of opcode names in the documentation to make them more intuitive.

 

Advanced Console Component 20220209.zip

Link to comment
Share on other sites

Another update!

 

The documentation now details all coprocessor instructions with the exception of which ones support SDBD. I also fixed some obscure bugs in the coprocessor code relating to division by zero and setting the overflow flag. I also expanded the SHLD and SHRD instructions to support shifts of more than 16 bits. Attachment below.

 

Advanced Console Component 20220210.zip

Edited by JohnPCAE
Link to comment
Share on other sites

On 1/8/2022 at 11:05 PM, JohnPCAE said:

I posted about the problem on the Firefox forums, and they pointed me to a solution. I had to go into my Firefox settings and clear the cache. All fixed now!

I had the exact same problems around that time using Firefox Windows 10 64x. I had someone else contact a moderator who e-mailed me that I had a problem with Javascript settings. I took a deep dive into Firefox settings and it said enabled and whole lot of other info, some I understood, some I didn't. Sent a copy to moderator. Then 2 days later, I tried Firefox again and it worked! I did not clear cache nor make any changes to Firefox.

 

Glad to know I wasn't the only one who had this problem for about a week or so.

Link to comment
Share on other sites

Another update.

 

I've added a few more instructions:

 

ADDBCR   RS, RD

ADDNCR   RS, RD

CCD2W     RD

COMS

 

ADDBCR adds a value in a source register to both bytes in the destination register, clamping each byte to the range 0..255 (no rollover).

ADDNCR is similar but it adds to each 4-bit nibble in the destination register, clamping them to the range 0..15.

CCD2W reads a 32-bit color at an indirect address, downconverts it to a 16-bit color, and writes it to the register that pointed to the color.

COMS flips the sign flag.

 

The first two instructions are useful for lighting effects when working in true-color mode. The third instruction enables quick conversion of, say, a 32-bit texture to 16-bit. As for the last instruction, now the instruction set has set, clear, and complement instructions for each of the flags.

 

Advanced Console Component 20220213.zip

Edited by JohnPCAE
Link to comment
Share on other sites

2 hours ago, BBWW said:

Sell this to Intellivision Entertainment. It could be the Intellivision we really want AND deliverable!

I know, right? At least this exists, unlike the Amico.

 

Anyway, I ran across a bug in my handling of the SHLD and SHRD instructions. Here is a small update that fixes it.

 

Advanced Console Component 20220215.zip

Link to comment
Share on other sites

I'm working on a series of assembler macros that will make writing coprocessor code easier. The idea is that you'd write whatever coprocessor routines you need and then have a standard CP-1600 routine copy them to ACC memory. When it's ready I'll bundle it in the ACC zip file and post an update.

Link to comment
Share on other sites

An update to the software:

 

- Removed some code for SHLD and SHRD that would never be used

- Updated the example Intellivision program to show writing some coprocessor instructions

- Updated the documentation

- Added an AS1600 source file that has macros for all coprocessor instructions

- Added a modified version of AS1600 that is required for the macro file (the same one as in the "Bug in AS1600?" thread)

Advanced Console Component 20220220.zip

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...