The official documents are not clear about the interrupt vector provided in mode 2, I found the following are correct:
{| class="wikitable"|-! Interrupt Source !! Vector|-| DMA Channel 0 || 4|-| DMA Channel 1 || 2|-| DMA Channel 2 || 0|-| Raster Interrupts || 6|}
The interrupt vector is therefore ((IVR & 0x0f8) | Vector).
There are two differences between the ASIC implementation of the 8255 PPI and the 8255 PPI inside the CPC:
* When the PPI Control register is re-programmed the output latches are not cleared. In the 8255 PPI used by the CPC and KC Compact the port output *is* cleared. Some games use this fact in the keyboard scanning algorithm, and as a result they will not work on the CPC+.* Port B is always defined as input and Port C is always defined as output.
The PPI in the ASIC is a cut-down version of the 8255PPI. It has all the operations used by the CPC including the bit set/reset feature. It may not have the functions to set the port operation (mode 0, 1 or 2) as these features are not used on the CPC (to my knowledge).
=== Notes ===
* Since the 8255 emulation in the ASIC lacks many features in a real 8255, it is doubtful if the mode operations will work. From the above, it appears that the input/output status of Port B or Port C cannot be controlled.The only port that the input/output status appears to make a difference is with port A.* The ASIC chip is designed to be used in the CPC+ only, and since port B is always used as input and port C is always used as output, it makes sense that the designers did not waste space on the chip to recreate the features of the original chip that were not used.
== CRTC ==
When reading, the following register data is returned:
{| class="wikitable"|-! 6845 Selected Register !! 6845 Register data returnedData Returned|-| 0 || 16|-| 1 || 17|-| 2 || Status 1 (note 1)|-| 3 || Status 2 (note 1)|-| 4 || 12|-| 5 || 13|-| 6 || (note 2)|-| 7 || (note 2)|-| 8 || 16|-| 9 || 17|-| 10 || Status 1 (note 1)|-| 11 || Status 2 (note 1)|-| 12 || 12|-| 13 || 13|-| 14 || (note 2)|-| 15 || (note 2)|-| 16 || 16|-| 17 || 17|-| 18 || Status 1 (note 1)|-| 19 || Status 2 (note 1)|-| 20 || 12|-| 21 || 13|-| 22 || (note 2)|-| 23 || (note 2)|-| 24 || 16|-| 25 || 17|-| 26 || Status 1 (note 1)|-| 27 || Status 2 (note 1)|-| 28 || 12|-| 29 || 13|-| 30 || (note 2)|-| 31 || (note 2)|}
Note:
* These do not appear to be actual CRTC registers. When read, they appear to give the status of the internal operation of the CRTC. I have named them "Status 1" and "Status 2" because they contain different information. These status registers are only present in the CPC+ version of the CRTC. I believe these registers were used to test the operation of the CRTC during development.* It is not clear if these registers hold any data, they always return "0".
=== Status 1 ===
When Status register 1 is read, the bits have the following meaning:
{| class="wikitable"|-| Bit 7 || (function of this bit is unknown)|-| Bit 6 || (function of this bit is unknown)|-| Bit 5 || 0: CRTC is on last line of VSYNC|-| Bit 4 || 0: CRTC is on last char of HSYNC|-| Bit 3 || 0: CRTC Horizontal Count == Horizontal Sync Position (Reg 2)|-| Bit 2 || 0: CRTC Horizontal Count == Horizontal Displayed (Reg 1)|-| Bit 1 || 0: CRTC Horizontal Count == (Horizontal Total/2)|-| Bit 0 || 0: CRTC Horizontal Count != Horizontal Total|}
=== Status 2 ===
When Status register 2 is read, the bits have the following meaning:
{| class="wikitable"|-| Bit 7 || 0: when RC!=0|-| Bit 6 || (function of this bit is unknown)|-| Bit 5 || 0: when RC==R9|-| Bit 4 || (function of this bit is unknown)|-| Bit 3 || (function of this bit is unknown)|-| Bit 2 || (function of this bit is unknown)|-| Bit 1 || (function of this bit is unknown)|-| Bit 0 || (function of this bit is unknown)|}
== ASIC Ram Information ==
Offsets are given from the base of the sprite information for each sprite.
{| class="wikitable"|-| Offset 0 || Low byte of X coordinate|-| Offset 1 || High byte of X coordinate|-| Offset 2 || Low byte of Y coordinate|-| Offset 3 || High byte of Y coordinate|-| Offset 4 || Sprite magnification|-| Offset 5 || Sprite magnification|-| Offset 6 || Sprite magnification|-| Offset 7 || Sprite magnification|}
When read, offset 4,5,6 and 7 (in that order) are a mirror of reading offset 0,1,2 and 3 (in that order).
=== Palette: ===
{| class="wikitable"|-| Entry Offset 0 || Upper nibble is Red, lower nibble is blueBlue|-| Entry Offset 1 || Lower nibble is Green.|}
When a byte is written to offset 1 and then read back it's value is returned & 0x0f. When writing to offset 0, and then read back, it's value is the same as written.
When a colour is set using the old method (using I/O), the corresponding entry in the ASIC Ram is updated with the RGB of the colour chosen. The table below shows the "hardware colour index" and the corresponding R,G,B for the colour.
{| class="wikitable"|-! Hardware Colour Index !! Colour Name RGB!! R !! G !! B|-| 0 || White || 6 || 6 || 6|-| 1 || White || 6 || 6 || 6|-| 2 || Sea Green || 0 || 15 || 6|-| 3 || Pastel Yellow || 15 || 15 || 6|-| 4 || Blue || 0 || 0 || 6|-| 5 || Purple || 15 || 0 || 6|-| 6 || Cyan || 0 || 6 || 6|-| 7 || Pink || 15 || 6 || 6|-| 8 || Purple || 15 || 0 || 6|-| 9 || Pastel Yellow || 15 || 15 || 6|-| 10 || Bright Yellow || 15 || 15 || 0|-| 11 || Bright White || 15 || 15 || 15|-| 12 || Bright Red || 15 || 0 || 0|-| 13 || Bright Magenta || 15 || 0 || 15|-| 14 || Orange || 15 || 6 || 0|-| 15 || Pastel Magenta || 15 || 6 || 15|-| 16 || Blue || 0 || 0 || 6|-| 17 || Sea Green || 0 || 15 || 6|-| 18 || Bright Green || 0 || 15 || 0|-| 19 || Bright Cyan || 0 || 15 || 15|-| 20 || Black || 0 || 0 || 0|-| 21 || Bright Blue || 0 || 0 || 15|-| 22 || Green || 0 || 6 || 0|-| 23 || Sky Blue || 0 || 6 || 15|-| 24 || Magenta || 6 || 0 || 6|-| 25 || Pastel Green || 6 || 15 || 6|-| 26 || Lime || 6 || 15 || 0|-| 27 || Pastel Cyan || 6 || 15 || 15|-| 28 || Red || 6 || 0 || 0|-| 29 || Mauve || 6 || 0 || 15|-| 30 || Yellow || 6 || 6 || 0|-| 31 || Pastel Blue || 6 || 6 || 15|}
The sprite colours can not be changed using the old method. To change the sprite colours, the ASIC must be enabled and the ASIC ram paged into the memory space.
Reading from 0x06800-0x06807 will read the same values as for invalid data.
* Writing to &6800 will set the interrupt raster line,* Writing to &6801 will set the screen split line,* Writing to &6802 and &6803 will set the screen split address,* Writing to &6804 will set the soft scroll,* Writing to &6805 will set the interrupt vector (Arnold V specification 1.4).* Writing to &6806 has no effect.* Writing to &6807 has no effect.
For the interrupt raster line, soft scroll and split line please see furthur in this document for details of how the ASIC generates the comparison value to compare against each of these programmed values.
However, I found that with this bit set to 0, there is a bug.
Example showing bug: [ [http://www.cpctech.org.uk/source/asicbug.html highlighted ] | [http://www.cpctech.org.uk/source/asicbug.asm original ] ]
A demo program used a single DMA channel to issue an interrupt, a few lines later a raster interrupt would issue an interrupt. The first interrupt executed the correct interrupt handler routine (0,2 or 4), the second executed the interrupt handler for vector of 0 (the raster interrupt is vector 6). This was clearly wrong! My advice is that you should not use the automatic interrupt clear feature.
Without any peripherals attached, the following readings were observed:
* ADC0: 0x03f* ADC1: 0x03f* ADC2: 0x03f* ADC3: 0x03f* ADC4: 0x03f* ADC5: 0x000* ADC6: 0x03f* ADC7: 0x000
Writing to these appears to have no effect, with the readings not changing.
The official documentation is not clear about the bits in the DCSR register (&6c0f), I found the following are correct:
{| class="wikitable"|-| Bit 7 || Raster Int|-| Bit 6 || DMA Channel 0 Interrupt|-| Bit 5 || DMA Channel 1 Interrupt|-| Bit 4 || DMA Channel 2 Interrupt|-| Bit 3 || not used|-| Bit 2 || DMA Channel 2 Enable|-| Bit 1 || DMA Channel 1 Enable|-| Bit 0 || DMA Channel 0 Enable|}
Each DMA opcode is two bytes, and is always fetched from an even address. The top 4-bits of the opcode fetched in the DMA cycle are used to specify the function to perform by the DMA.
I found the following rule:
bit {| class="wikitable"|-| Bit 3 || not used|-| Bit 2 || Nop/loop/Int/Stop instruction|-| Bit 1 || Repeat N instruction|-| Bit 0 || Pause instruction.|}
If (opcode & 0x07 == 0) then write data to register else perform function defined by bits.
For those who do not know this language, here is a quick list of the operators and their functions:
* | - bitwise/logical OR* & - bitwise/logical AND* << - shift left by number of bits specified* >> - shift right by number of bits specified* == - equals comparison* = - assign value to variable* && - and, as used in "if a==b and c==d ..."
Hex numbers are represented with a prefix of 0x. e.g. 0x0abcd is the hex number abcd.
In if statements, the operations enclosed in { } brackets following the if are executed if the condition is true, otherwise the operations enclosed in the brackets following the "else" statement are executed.
In the ASIC documentation it states that following the leading edge of the HSYNC, there is one dead cycle, followed by an instruction fetch for each channel. For each cycle 1 2 byte instruction is fetched.
When competition pro attached only.
* 6808 = left/right* 6809 = up/down* 680a = Z button* 680b = y button
pressing X button sets bit 4 of all keys on keyboard matrix, pressing A button sets bit 5 of all keys on keyboard matrix
pressing delete causes all lines to go to 0x080, except line 15. All keys except delete work as expected.
* keyboard normally all keys pressed gives 0-9 0x0ff* 10 is joystick* anything above 10 is zero.
=== joypad and analogue joypad ===
Microsoft sidewinder doesn't work!
[[Category:Hardware]] [[Category:CPC Plus]] [[Category:CPC Internal Components]]