-
Tick Tock
10/09/2021 at 15:28 • 0 commentsFollowing on from the interrupts work, I now have the RTC, a 100hz timer and millisecond 32 bit-counter up and running. The 100hz interrupt can be switched on or off, the millisecond timer starts counting at system start. That I think is the last of the hardware for the moment. Time to move on to creating a small boot routine to load up a larger program from the sd card. I've been using my own version of the zBug monitor which I nabbed from this project when I first started on my own 68000 system. I wouldn't have got started without that project and the Easy68k simulator.
https://github.com/kanpapa/mic68k -
More interrupts
10/08/2021 at 14:10 • 1 commentSo auto-vector interrupts are now available.
A tweak to the monitor switches on interrupts by moving $2000 to the stack register.
The 68000 has 7 auto-vectored interrupts which are located at specific addresses in the memory:
#define int1 0x64 #define int2 0x68 #define int3 0x6c #define int4 0x70 #define int5 0x74 #define int6 0x78 #define int7 0x7c
The cpu expects a 3-bit interrupt number. I have an vhdl interrupt controller which manages the 7 hardware interrupts, provides the 3-bit number and then clears them when the CPU goes into the interrupt acknowledge cycle (FC = 7).
interrupts: entity work.interrupt_controller port map ( clk => sys_clk, reset => n_reset, int1 => timer_in1, int2 => timer_in2, int3 => keyb_int, int4 => '0', int5 => '0', int6 => '0', int7 => '0', int_out => int_out, ack => auto_iack ); auto_iack <= '1' when cpu_fc = "111" else '0';
To provide an interrupt handler the following code will update the memory address contained in these locations.
void setKeyboardHandler(void(*handler)()) { asm( "move.l %0,0x6c": : "r" (handler) :); volatile uint32_t *keyb_int = (uint32_t*)int3; printf("\r\nKeyboard address = 0x%0lX\r\n", *keyb_int); } setKeyboardHandler(&keyboardHandler);
An infinite loop can then run and then only be interrupted when the keyboard is pressed on "int3" - this would cause a call to the code located at address 0xF74.
-
Interrupts
10/06/2021 at 16:58 • 0 commentsNow that the FPU is working (phew). I'm now concentrating on getting timers, keyboard and interrupts working. I am using a pmod ps2 to connect to an old compaq keyboard I found in my loft. Currently the first interrupt for the keyboard is working. At the moment it bombs in the loop, not sure why but this is an improvement in that it now picks up the ascii code and pops it on the screen without polling.
-
Faster Cobra
09/25/2021 at 07:20 • 0 commentsNow that I have a fully working FPU, the Cobra demo works much better. The animation is much smoother.
-
Finished FPU
09/25/2021 at 06:55 • 0 commentsFinally got a stable working FPU which is compatible with printf. I was surprised by the amount of maths used to print a floating point number. I have new wrapper functions now which replace the 68000 FP emulation code provided with the gcc compiler. This means that math functions are now sent to the FPU without requiring further code changes.
Using the framebuffer of the Gameduino Dazzler I was able to produce a really nice HD mandelbrot set. The calculations run a lot faster now with the hardware FPU. -
More FP
08/16/2021 at 08:30 • 0 commentsI have a 64-bit double precision FPU working now. It seems to be a big improvement on my first version. The main work now is to complete the new library for GCC to make use of the FPU.
I have started to work on a set of wrapper functions which will override the existing soft-float routines.
The first routine overrides muldf3:double __wrap___muldf3(double a, double b) { printf("\r\nmuldf3: start\r\n"); *fpu_ctl = MUL; op_a.dbl = a; op_b.dbl = b; *opa = op_a.num; *opb = op_b.num; BIT_SET(*fpu_ctl, 0); BIT_CLEAR(*fpu_ctl, 0); while (!BIT_CHECK(*fpu_sts, 0) && !BIT_CHECK(*fpu_sts, 1)) { } resf.num = *fpu_res; printf("\r\nmuldf3: stop\r\n"); return resf.dbl; }
It uses a union to convert the double to IEEE754 double-precision int.
union FloatingPointIEEE754 { struct { unsigned int sign : 1; unsigned short int exponent : 11; long long mantissa : 52; } raw; uint64_t num; double dbl; } ;
The make file has an additional parameter to override the specified function.
float-test.run: ieee754.c float-test.c m68k-elf-gcc -Wall -m68000 -g -Os ieee754.c float-test.c -Wl,--wrap=__muldf3 -o float-test.run ....
-
More FP
08/16/2021 at 08:30 • 0 commentsI have a 64-bit double precision FPU working now. It seems to be a big improvement on my first version. The main work now is to complete the new library for GCC to make use of the FPU.
I have started to work on a set of wrapper functions which will override the existing soft-float routines.
The first routine overrides muldf3:double __wrap___muldf3(double a, double b) { printf("\r\nmuldf3: start\r\n"); *fpu_ctl = MUL; op_a.dbl = a; op_b.dbl = b; *opa = op_a.num; *opb = op_b.num; BIT_SET(*fpu_ctl, 0); BIT_CLEAR(*fpu_ctl, 0); while (!BIT_CHECK(*fpu_sts, 0) && !BIT_CHECK(*fpu_sts, 1)) { } resf.num = *fpu_res; printf("\r\nmuldf3: stop\r\n"); return resf.dbl; }
It uses a union to convert the double to IEEE754 double-precision int.
union FloatingPointIEEE754 { struct { unsigned int sign : 1; unsigned short int exponent : 11; long long mantissa : 52; } raw; uint64_t num; double dbl; } ;
The make file has an additional parameter to override the specified function.
float-test.run: ieee754.c float-test.c m68k-elf-gcc -Wall -m68000 -g -Os ieee754.c float-test.c -Wl,--wrap=__muldf3 -o float-test.run ....
-
Floating Point
07/28/2021 at 14:33 • 0 commentsI have updated and modified an FPU from opencores. I removed the division/square root code and put in xilinix optimised code. It now runs at 200mhz as opposed to the original 100mhz.
Using the FPU for this code:
for (int i = 0; i<5000; i++) { res = (a+i)/(b-i); res = res * a * (i/b); if (res < 0) { res = res*-1.0; } res = sqrtf(res); printf("res = %0.3f\r\n",res); }
I managed to improve the performance substantially over the already optimised 68k assembler code provided in the soft-float gcc library. Also tg68 has a hardware multiplier built in so this is quite a large improvement.
I would expect larger improvements if just using ieee754 numbers rather than relying on conversion from floats all the time.
Any way from the built in timer.time taken. fpu: 46149 sf: 51679
-
Framebuffer
07/20/2021 at 10:34 • 0 commentsThe Dazzler has 1mb of vram available to it. Normally you send commands down spi to create images, text and so on. But you can use a Paletted bitmap to create a 1280x720 framebuffer with a palette and around 120k left for other data.
After raising a question on the gameduino forum James Bowman kindly wrote a quick demo on how to create a random image pixel by pixel. I've taken that example and have created a fractal generator which I'll share very soon. Here's a link to the arduino sketch demo from James.
https://github.com/jamesbowman/gd2-lib/blob/master/examples/paletted.ino -
OPL3 live!
07/17/2021 at 12:07 • 0 commentsI have implemented a millisecond timer and converted an Arduino OPL library. This demo shows the cards and you can hear a simple music track playing.
Code available here:
https://github.com/mattuna15/merlin-software/tree/master/ArduinoOPL2