[posted] VGA out for Teensy 4.0/4.1

Fantastic!
Go on for the 12 bit. It is so good to have an Amiga again. Thank you!
 
So nice :)
I just have to wait for some components and i try it , Amiga Forever ;)
Is the teensy 4.1 uae version updated for VGA on your github ? , i have look but i think it's the ili9341 version.

Cheers.
 
Emulator's code adapted for VGA is not yet published. Still trying to fix higher resolution for the Amiga and Atari ST!
 
some new graphics functions ...

After playing around i added some functionalities to the graphics lib :

void drawline(int16_t x1, int16_t y1, int16_t x2, int16_t y2, vga_pixel color);
void drawcircle(int16_t x, int16_t y, uint16_t radius, vga_pixel color);
void drawfilledcircle(int16_t x, int16_t y, int16_t radius, vga_pixel fillcolor, vga_pixel bordercolor);
void drawellipse(int16_t cx, int16_t cy, uint16_t radius1, uint16_t radius2, vga_pixel color);
void drawfilledellipse(int16_t cx, int16_t cy, uint16_t radius1, uint16_t radius2, vga_pixel fillcolor, vga_pixel bordercolor);
void drawtriangle(int16_t ax, int16_t ay, int16_t bx, int16_t by, int16_t cx, int16_t cy, vga_pixel color);
void drawfilledtriangle(int16_t ax, int16_t ay, int16_t bx, int16_t by, int16_t cx, int16_t cy, vga_pixel fillcolor, vga_pixel bordercolor);

you can see the result here :
https://drive.google.com/file/d/1qb_T9d1RTNZqkkz_75CRN3HInjJrsr14/view?usp=sharing

I just see one problem , the circle are ... ovale ;)

The horizontal and vertical lines are spaced from 10 pixels , here we see that the pixels have a size in x of 2 and 1 in Y.

Well ... i will go for manage my circle differently :)

Cheers.

PS : for the schematic , take this one , it's the original before reduction :
https://drive.google.com/file/d/15tzG6HwElvlZym2a9YxOU0MsCzWxibKU/view?usp=sharing
 
Thanks. I will merge your code into the git tomorrow.

In meanwhile, I pushed the VGA support code to the teensyuae41.

https://github.com/Jean-MarcHarvengt/MCUME

I was trying the all day to introduce a 640x240 mode but I don't manage.
Still runs at 352x240 (320x240 in fact) wo sound but not too bad...even in RRRGGGBB mode.

Pay attention to iopins.h for the 3 keys needed an the joypad,... and you the need psram soldered of course!
 
Here is the source from my old STM32 library for the exact timing of some VGA resolution :

HSync_Level and VSync_Level change , it depend the resolution , you have to take care on this too ...
PLLSAI_VCO , PLLSAI_R , PLLSAIDivR are just for STM32Fxx timing .... most important is to stay in the 25.175Mhz range , a little drift is working so long it's not too much :D
I hope it can help you for the 640 x 240 resolution ...

Code:
// VGA Parameter common to all resolution made with
// the standard 640x480 at 60Hz base.
// 25.175Mhz base (here is 25.187 Mhz)
#if defined USE_240x320_60 || defined USE_320x240_60 || defined USE_320x240_60_DOUBLE || defined USE_640x480_60
	#define GFX_H_Front_Porch				((uint16_t)8)	//pixels
	#define GFX_H_Sync						((uint16_t)96)	//pixels
	#define GFX_H_Back_Porch				((uint16_t)40)	//pixels
	#define GFX_V_Front_Porch				((uint16_t)2)	//lines
	#define GFX_V_Sync						((uint16_t)2)	//lines
	#define GFX_V_Back_Porch				((uint16_t)25)	//lines
	#define GFX_Total_line_length			        ((uint16_t)800)	//pixels
	#define GFX_Total_Height				        ((uint16_t)525)	//lines
	#define Freq_PLLSAI_VCO					((uint16_t)403)	//Mhz
	#define Freq_PLLSAI_R					((uint16_t)2)	//Div 2 (403/2 = 201.5 Mhz)
	#define Freq_PLLSAIDivR					((uint16_t)7)	//Div 8	(201.5/8 = 25.187 Mhz) do -1 from divider
	#define HSync_Level						((uint16_t)0)	//Low
	#define VSync_Level						((uint16_t)0)	//Low
#endif

#ifdef USE_240x320_60
	#define GFX_H_Left_Border				((uint16_t)208)	//pixels
	#define GFX_H_Video_Line				        ((uint16_t)240)	//pixels
	#define GFX_H_Right_Border				((uint16_t)208)	//pixels
	#define GFX_V_Top_Border				((uint16_t)88)	//lines
	#define GFX_V_Video_Height				((uint16_t)320)	//lines
	#define GFX_V_Bottom_Border				((uint16_t)88)	//lines
#endif

#ifdef USE_320x240_60
	#define GFX_H_Left_Border				((uint16_t)168)	//pixels
	#define GFX_H_Video_Line				        ((uint16_t)320)	//pixels
	#define GFX_H_Right_Border				((uint16_t)168)	//pixels
	#define GFX_V_Top_Border				((uint16_t)128)	//lines
	#define GFX_V_Video_Height				((uint16_t)240)	//lines
	#define GFX_V_Bottom_Border				((uint16_t)128)	//lines
#endif

#ifdef USE_320x240_60_DOUBLE
	#define GFX_H_Left_Border				((uint16_t)8)	//pixels
	#define GFX_H_Video_Line				        ((uint16_t)640)	//pixels
	#define GFX_H_Right_Border				((uint16_t)8)	//pixels
	#define GFX_V_Top_Border				((uint16_t)8)	//lines
	#define GFX_V_Video_Height				((uint16_t)480)	//lines
	#define GFX_V_Bottom_Border				((uint16_t)8)	//lines
#endif

#ifdef USE_640x480_60
	#define GFX_H_Left_Border				((uint16_t)8)	//pixels
	#define GFX_H_Video_Line				        ((uint16_t)640)	//pixels
	#define GFX_H_Right_Border				((uint16_t)8)	//pixels
	#define GFX_V_Top_Border				((uint16_t)8)	//lines
	#define GFX_V_Video_Height				((uint16_t)480)	//lines
	#define GFX_V_Bottom_Border				((uint16_t)8)	//lines
#endif

#ifdef USE_640x350_70 //25.175 Mhz
	#define GFX_H_Left_Border				((uint16_t)0)	//pixels
	#define GFX_H_Video_Line				        ((uint16_t)640)	//pixels
	#define GFX_H_Right_Border				((uint16_t)0)	//pixels
	#define GFX_V_Top_Border				((uint16_t)0)	//lines
	#define GFX_V_Video_Height				((uint16_t)350)	//lines
	#define GFX_V_Bottom_Border				((uint16_t)0)	//lines
	#define GFX_H_Front_Porch				((uint16_t)16)	//pixels
	#define GFX_H_Sync						((uint16_t)96)	//pixels
	#define GFX_H_Back_Porch				((uint16_t)48)	//pixels
	#define GFX_V_Front_Porch				((uint16_t)37)	//lines
	#define GFX_V_Sync						((uint16_t)2)	//lines
	#define GFX_V_Back_Porch				((uint16_t)60)	//lines
	#define GFX_Total_line_length			        ((uint16_t)800)	//pixels
	#define GFX_Total_Height				        ((uint16_t)449)	//lines
	#define Freq_PLLSAI_VCO					((uint16_t)403)	//Mhz
	#define Freq_PLLSAI_R					((uint16_t)2)	//Div 2 (403/2 = 201.5 Mhz)
	#define Freq_PLLSAIDivR					((uint16_t)7)	//Div 8	(201.5/8 = 25.187 Mhz) do -1 from divider
	#define HSync_Level						((uint16_t)1)	//High
	#define VSync_Level						((uint16_t)0)	//Low
#endif

#ifdef USE_640x400_70 //25.175 Mhz
	#define GFX_H_Left_Border				((uint16_t)0)	//pixels
	#define GFX_H_Video_Line				        ((uint16_t)640)	//pixels
	#define GFX_H_Right_Border				((uint16_t)0)	//pixels
	#define GFX_V_Top_Border				((uint16_t)0)	//lines
	#define GFX_V_Video_Height				((uint16_t)400)	//lines
	#define GFX_V_Bottom_Border				((uint16_t)0)	//lines
	#define GFX_H_Front_Porch				((uint16_t)16)	//pixels
	#define GFX_H_Sync						((uint16_t)96)	//pixels
	#define GFX_H_Back_Porch				((uint16_t)48)	//pixels
	#define GFX_V_Front_Porch				((uint16_t)12)	//lines
	#define GFX_V_Sync						((uint16_t)2)	//lines
	#define GFX_V_Back_Porch				((uint16_t)35)	//lines
	#define GFX_Total_line_length			        ((uint16_t)800)	//pixels
	#define GFX_Total_Height				        ((uint16_t)449)	//lines
	#define Freq_PLLSAI_VCO					((uint16_t)403)	//Mhz
	#define Freq_PLLSAI_R					((uint16_t)2)	//Div 2 (403/2 = 201.5 Mhz)
	#define Freq_PLLSAIDivR					((uint16_t)7)	//Div 8	(201.5/8 = 25.187 Mhz) do -1 from divider
	#define HSync_Level						((uint16_t)0)	//Low
	#define VSync_Level						((uint16_t)1)	//High
#endif
 
[sorry to snoop on the "Quad" code, but I couldn't help noticing]

I'm sure you only need to call sine and cosine once each for the rectangle drawing, using transformation
matrix... Transform one coord of one corner (w/2, h/2), transform two vectors for the sides (w, 0), (0, h),
reconstruction of the other corners is then addition/subtraction of vectors.

Calculating four different angles doesn't seem an efficient method to me.
 
I just tested uae on T4.1 ;)
So great to see a full speed Amiga coming out of this little Teensy !!
I need now a keyboard , i take a look at your i2c keyboard , your schematic is 'Ugly' :)
Do you have something more explicit to build the KB ? , you use Atmega328 (same as arduino nano) , now your pinout and key distribution made some knot into my poor brain.
It will be better with a real schematic or is it possible to connect a usb kb directly ?
Some game need more than one disk , and i was not able to 'change' disk when requested , is it a way to do it ?

Cheers.
 
The original idea was to create a portable amiga with the ILI display, so I had chosen to build a I2C interfaced keyboard matrix ;-)

I did not try to add usb keyboard support but should be doable.
I need to find a usb cable. I can have a look this week.

I received my PCM5102a sound module today.
I just connected it over I2S and it sounds great together with the VGA out.
It disturbs the line interrupt a bit but sound is ok!
 
May I ask you to try something for me...
You probably have a better cable than me and you also use the R2R ladder you proposed.
Could try to activate sound in platform_config.h on the amiga emulator.
Just uncomment HAS_SOUND line...

Do you also have disturbance on the video lines?
 
Impressive the 1062 allows upgrade from the 6502!

For USB Host keyboard ref perhaps:: On github.com/FrankBoesing/Teensy64 3 years back - Commodore C64 Emulation on a Teensy 3.6 Microcontroller used USB for keyboard - also did VGA and ILI9341. It also had PS/2 keyboard support.
 
Hi :D

Today i connected a PS2 or (USB to PS2) keyboard to a arduino nano who read the KB and send the character out to I2C when requested.
Is it something to know to made it work like your I2C KB ? so it will be good for all of your emulators.

Cheers.
 
It is a great idea indeed. The I2C protocol is quite simple. I just reads (one single read command) an array of bytes where each bit reflects the status of one key. I had 2 variants. 4 rows of 10 keys (4bits-4bits-4bits ...4bits grouped in bytes per 2 columns) => 5 bytes. I also had variant with 5 rows of 10 keys but the portable console T4 has only 4x10 keys.

About Teensy64, it is indeed the project of Frank! I forked the code when I added support for a on screen keyboard using the ILI touch screen when using the VGA output (uVGA) on the T3.6.

I tried activating USB and I think it will also work to add USB keyboard directly on UAE. I found a USB connector I will try to connect it to the T4 tomorrow.

I am off next week so I will measure the accuracy of the H-pulses with a scope. Still did not manage to get proper clock for 640x240.
I think it was a miracle to have 352x240 working!

Thanks for your interest to the project ;-)
 
Hi :)

Strange that you can't get the 640 x 240 resolution , it must be something with the timing.
I got problems with that some years ago with the STM32F407 MCU , when everything was ok the 640 x 480 native VGA was perfect.
Now with STM32H7 i'm sure we can have the 800x600 or 1024x768 , but it use the DMA2D + LTDC ...
Teensy 4.1 got 200+ Mhz than the STM32H7 then it will work too ... for sure ... ;)
Now for the keyboard , i found this in 'emuapi.h' :
Code:
#ifdef HAS_I2CKBD
const unsigned short i2ckeys[] = {
     0X0080,0X0008,0X0180,0X0108,0X0280,0X0208,0X0380,0X0308,0X0480,0X0408,
     0X0040,0X0004,0X0140,0X0104,0X0240,0X0204,0X0340,0X0304,0X0440,0X0404,
     0X0020,0X0002,0X0120,0X0102,0X0220,0X0202,0X0320,0X0302,0X0420,0X0402,
     0X0010,0X0001,0X0110,0X0101,0X0210,0X0201,0X0310,0X0301,0X0410,0X0401 };
     //0X0580,0X0540,0X0520,0X0510,0X0508,0X0504,0X0502,0X0501,0X0680,0X0640 };
#endif

I presume that is the keycode , you are using 40 keys , on your picture they are no characters written on the keys :eek:
Is there a corresponding table to know what key trigger what character ?
I will take it as example for finish my actual setup with the i2c (real keyboard).
Only KB with cable are working actually , i tested 2 wireless KB with no luck.

I tried activating USB and I think it will also work to add USB keyboard directly on UAE
I hope it will not take precious resources :)

Thanks for your interest to the project ;-)
Lol , thanks to you who made it work !

Cheers.
 
indeed, each emulator in MCUME (computer with a keyboard) has a similar table.
The table you pasted above is somehow derived from the I2C data read (see emuapi.cpp for details). Kind of row+col code.

Next to that you have a keymap table of same size with the code injected to the emulator itself.

In case of the amiga, there are 2 keymaps table. One where Function keys are sent in first row, one where digits are sent.
You toggle via a user button between the 2 keymaps

Not all keys are mapped in current layout but it can be extended.

const unsigned short key_map1[]={

1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37, 38, 39, 40 };

const unsigned short key_map2[]={

41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
51, 52, 53, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
31, 32, 33, 34, 35, 36, 37, 38, 39, 40 };

In case of the amiga each entry in the keymap is an index to the amiga key but does not matter.
 
Ok :)

So i will look that my I2C code correspond to yours.
Is just that i put only one char on I2C bus each time , i see in 'emuapi.c' that you get 7 bytes each time ....
So i have to made some mods :D
Or add a new #define for 102 key KB ... will see ....
Thanks for your infos :)

Cheers.
 
Back
Top