1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-02-16 18:30:37 +00:00

Added MEGA65 math unit. Using math unit in line drawing.

This commit is contained in:
jespergravgaard 2021-04-01 19:33:48 +02:00
parent 920e0011ba
commit 51e7441e62
3 changed files with 74 additions and 5 deletions

View File

@ -0,0 +1,52 @@
// MEGA65 CPU MATHS ACCELERATION REGISTERS
// Every MEGA65 contains a combined 32-bit hardware multiplier and divider. This device
// takes two 32-bit inputs, MULTINA and MULTINB, and simultaneously calculates:
// • the 64-bit product of MULTINA and MULTINB
// • the 32-bit whole part of MULTINA / MULTINB
// • the 32-bit fractional part of MULTINA / MULTINB
// It is always updating the outputs based on the inputs, so there is no need to take special
// action when changing the inputs. The multiplier takes 1 cycle to calculate, and the updated result will thus be available immediately.
// The hardware divider, however, can take up to 16 cycles depending on the particular inputs. Thus programmers should insert a short
// delay after changing the inputs before reading the output. As this delay is so short, it can be implemented by simply reading the first
// byte of the result four times consecutively, as the 4th read will occur after the result has settled.
// $D70F MATH BUSY
// Bit 7: DIVBUSY
// Bit 6: MULBUSY
char * const MATH_BUSY = 0xd70f;
// $D768-$D76F DIVOUT 64-bit output of MULTINA ÷ MULTINB
// $D768-$D76B DIVOUT FRAC 32-bit output of MULTINA ÷ MULTINB
signed char * const MATH_DIVOUT_FRAC_CHAR0 = 0xd768;
signed int * const MATH_DIVOUT_FRAC_INT0 = 0xd768;
signed int * const MATH_DIVOUT_FRAC_INT1 = 0xd76a;
signed long * const MATH_DIVOUT_FRAC_LONG0 = 0xd768;
// $D768-$D76F DIVOUT 64-bit output of MULTINA ÷ MULTINB
signed char * const MATH_DIVOUT_WHOLE_CHAR0 = 0xd76c;
signed int * const MATH_DIVOUT_WHOLE_INT0 = 0xd76c;
signed int * const MATH_DIVOUT_WHOLE_INT1 = 0xd76e;
signed long * const MATH_DIVOUT_WHOLE_LONG = 0xd76c;
// $D770-$D773 MULTINA Multiplier input A / Divider numerator (32 bit)
signed char * const MATH_MULTINA_CHAR0 = 0xd770;
signed char * const MATH_MULTINA_CHAR1 = 0xd771;
signed char * const MATH_MULTINA_CHAR2 = 0xd772;
signed char * const MATH_MULTINA_CHAR3 = 0xd773;
signed int * const MATH_MULTINA_INT0 = 0xd770;
signed int * const MATH_MULTINA_INT1 = 0xd772;
signed long * const MATH_MULTINA_LONG = 0xd770;
// $D774-$D777 MULTINB Multiplier input B / Divider denominator (32 bit)
signed char * const MATH_MULTINB_CHAR0 = 0xd774;
signed char * const MATH_MULTINB_CHAR1 = 0xd775;
signed char * const MATH_MULTINB_CHAR2 = 0xd776;
signed char * const MATH_MULTINB_CHAR3 = 0xd777;
signed int * const MATH_MULTINB_INT0 = 0xd774;
signed int * const MATH_MULTINB_INT1 = 0xd776;
signed long * const MATH_MULTINB_LONG = 0xd774;
// $D778-$D77F MULTOUT 64-bit output of MULTINA × MULTINB
signed char * const MATH_MULTOUT_CHAR0 = 0xd778;
signed int * const MATH_MULTOUT_INT0 = 0xd778;
signed long * const MATH_MULTOUT_LONG0 = 0xd778;
signed long * const MATH_MULTOUT_LONG1 = 0xd77c;

View File

@ -9,6 +9,7 @@
#include <mega65-viciv.h>
#include <mega65-memorymapper.h>
#include <mega65-f018.h>
#include <mega65-math.h>
// I/O Personality selection
volatile char * const IO_KEY = 0xd02f;

View File

@ -164,7 +164,7 @@ void draw_line(int x1, int y1, int x2, int y2, unsigned char colour)
y2 = temp;
}
// Use hardware divider to get the slope
/*
POKE(0xD770, (char)(dx & 0xff));
POKE(0xD771, (char)(dx >> 8));
POKE(0xD772, 0);
@ -173,7 +173,14 @@ void draw_line(int x1, int y1, int x2, int y2, unsigned char colour)
POKE(0xD775, (char)(dy >> 8));
POKE(0xD776, 0);
POKE(0xD777, 0);
*/
// Use hardware divider to get the slope
*MATH_MULTINA_INT0 = dx;
*MATH_MULTINB_INT0 = dy;
*MATH_MULTINA_INT1 = 0;
*MATH_MULTINB_INT1 = 0;
// Wait 16 cycles
POKE(0xD020, 0);
POKE(0xD020, 0);
@ -182,7 +189,8 @@ void draw_line(int x1, int y1, int x2, int y2, unsigned char colour)
// Slope is the most significant bytes of the fractional part
// of the division result
slope = (int)PEEK(0xD76A) + ((int)PEEK(0xD76B) << 8);
// slope = (int)PEEK(0xD76A) + ((int)PEEK(0xD76B) << 8);
slope = *MATH_DIVOUT_FRAC_INT1;
// Put slope into DMA options
line_dma_command[LINE_DMA_COMMAND_SLOPE_OFFSET] = (char)(slope & 0xff);
@ -230,6 +238,7 @@ void draw_line(int x1, int y1, int x2, int y2, unsigned char colour)
}
// Use hardware divider to get the slope
/*
POKE(0xD770, (char)(dy & 0xff));
POKE(0xD771, (char)(dy >> 8));
POKE(0xD772, 0);
@ -238,6 +247,13 @@ void draw_line(int x1, int y1, int x2, int y2, unsigned char colour)
POKE(0xD775, (char)(dx >> 8));
POKE(0xD776, 0);
POKE(0xD777, 0);
*/
// Use hardware divider to get the slope
*MATH_MULTINA_INT0 = dy;
*MATH_MULTINB_INT0 = dx;
*MATH_MULTINA_INT1 = 0;
*MATH_MULTINB_INT1 = 0;
// Wait 16 cycles
POKE(0xD020, 0);
@ -245,9 +261,9 @@ void draw_line(int x1, int y1, int x2, int y2, unsigned char colour)
POKE(0xD020, 0);
POKE(0xD020, 0);
// Slope is the most significant bytes of the fractional part
// of the division result
slope = (int)PEEK(0xD76A) + ((int)PEEK(0xD76B) << 8);
// Slope is the most significant bytes of the fractional part of the division result
// slope = (int)PEEK(0xD76A) + ((int)PEEK(0xD76B) << 8);
slope = *MATH_DIVOUT_FRAC_INT1;
// Put slope into DMA options
line_dma_command[LINE_DMA_COMMAND_SLOPE_OFFSET] = (char)(slope & 0xff);