Trying to bring something like uVGA library to the Teensy4.
Now all MCUME emulators support VGA output!!!
https://www.youtube.com/watch?v=UE9MPr-iVOg
https://github.com/Jean-MarcHarvengt/VGA_t4
Printable View
Trying to bring something like uVGA library to the Teensy4.
Now all MCUME emulators support VGA output!!!
https://www.youtube.com/watch?v=UE9MPr-iVOg
https://github.com/Jean-MarcHarvengt/VGA_t4
Nice work!
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!
I just made a R2R VGA DAC that output perfect colors , but when i try to upload the schematic (png 1280 x 688) it don't work.
So the schematic is dropped to google drive : https://drive.google.com/file/d/12U0...ew?usp=sharing
Cheers.
This VGA to HDMI converter work fine with your project :
https://www.amazon.fr/gp/product/B01...?ie=UTF8&psc=1
It's french amazon , but it must be available on other country too ...
Cheers.
I will upload the schematic to the GIT website. Thanks a lot!
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_...ew?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/15tz...ew?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!
The code is here :
https://drive.google.com/file/d/1il8...ew?usp=sharing
I don't have finished the "Quad" function , it need pre calculed sin/cos for efficiency , as i am new in teensy world , i have do allot with STM32F4 / F7 in the past , and need some time to understand how everything is working :)
And thanks for your code update , i will test it tomorrow ;)
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 :)
I tested , i get disturbance in video line , when sound is activated.
I2C Keyboard is a good idea , but then we need a ... real ... schematic ;)
On this picture you can see the disturbance on the vertical lines (you have to zoom in):
https://drive.google.com/file/d/1cO7...ew?usp=sharing
Cheers.
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' :
I presume that is the keycode , you are using 40 keys , on your picture they are no characters written on the keys :eek: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
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 hope it will not take precious resources :)Quote:
I tried activating USB and I think it will also work to add USB keyboard directly on UAE
Lol , thanks to you who made it work !Quote:
Thanks for your interest to the project ;-)
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.
IIRC there was some timing noise/jitter introduced with USB on the original VGA - with T_3.6 - that went into the Teensy64. But it still allowed ALL of C64 to run there. Initially Frank did a private USBHost it seems to disable/alter something - but scan at that old github looked like he went to PJRC release?
Timing and USB different of course with 1062 and faster USB - for better or worse.
I enjoyed working along with FrankB - good to have somebody else on board. And as cool as the T_3.6 was back then ... T_4.1 with PSRAM and more other is a step up.
Frank is definitively a great guy. Very knowledgeable and who contributed to many things on this forum, next to his own projects.
May be someone has a clue why i2s audio is also causing jitter on my qtimer3 line interrupt. Teensy3.6 has its own DAC and was not interfering with uVGA. May be I should try another qtimer or another timer than timer 3 in qtimer 3? I tried raising the priority of qtimer3 ISR but not much change. Not sure how to decrease I2S ISR to see if any effect.
Indeed - FrankB has done some awesome things - hopefully he'll be back from his break and all moved into his new place and ready for more Teensy fun in good time.
@luni or others might have good feedback on timers. They are a bit different and not all for the better than T_3.6 it seems. Interrupts are a bit less efficient on timers and pin interrupts are all cascaded across a single interrupt with the default 1062 switched to fast GPIO.
KurtE made yield() less intrusive and faster to check the serialEvent_X_() things. But doing a "void yield() {}" in sketch can still make even that 'weak' thing go away, as long as none of the Event code [ Arduino serialEvent(), or PJRC's eventResponder's ] are in use. That yield() is called on every exit of loop() - and on delay() as well.
USB keyboard is working fine. I wired the connector and it all went fine with my wireless keyboard. I added a table for handling main keys in the emulator. It works but I have to handle the release differently as that version of UAE does no handle keyup properly. I hope to share the code. I used the keyboard class part of the host library. Hard to say if there is disturbancel effect at this point...!
Hi :)
Great news if we can use directly a USB KB , i was trying to understand how to use my version ( 1 char sent per I2C at a time ) , but how it's done in UAE it's like to try to find out your way in a maze ;)
In your VGA Lib i see this :
Is this correct ? , 1st for 12 bits / pixels you use FLEXIO_SHIFTCFG_PWIDTH(16); // 16-bit parallel shift width , but for 8 bits/pixel you use FLEXIO_SHIFTCFG_PWIDTH(4); // 8-bit parallel shift width , why is there a 4 in the parameter ?Code:#ifdef BITS12
parallelWidth = FLEXIO_SHIFTCFG_PWIDTH(16); // 16-bit parallel shift width
pinSelect = FLEXIO_SHIFTCTL_PINSEL(0); // Select pins FXIO_D0 through FXIO_D12
#else
parallelWidth = FLEXIO_SHIFTCFG_PWIDTH(4); // 8-bit parallel shift width
pinSelect = FLEXIO_SHIFTCTL_PINSEL(0); // Select pins FXIO_D0 through FXIO_D3
#endif
some lines after thoose you use :
Again for 5 bit shift you use 5 but for 8 bit shift you use 4 :D ....Code:#ifdef BITS12
parallelWidth = FLEXIO_SHIFTCFG_PWIDTH(5); // 5-bit parallel shift width
pinSelect = FLEXIO_SHIFTCTL_PINSEL(4); // Select pins FXIO_D4 through FXIO_D8
#else
parallelWidth = FLEXIO_SHIFTCFG_PWIDTH(4); // 8-bit parallel shift width
pinSelect = FLEXIO_SHIFTCTL_PINSEL(4); // Select pins FXIO_D4 through FXIO_D7
#endif
I don't know if it's correct , but if not then you can presume that some graphics tearing can come from here.
When i made it on STM32Fxx i have use this info and take the 640 x 480 60Hz resolution as base of all other res i made.
https://drive.google.com/file/d/1W3Y...ew?usp=sharing
For example :
320 x 240 res was just 640 x 480 but with 2x bigger pixels
now for your 512 x 480 i will add 64 black pixels border on left and right , the advantage is that the pixel ratio is still OK , and when you trace a circle it appear as circle and not as oval :)
And it's working on the 640 x 480 base resolution.
I just hope i explain correctly :D VGA is not a easy stuff ... he he
Cheers.
The 12bits mode is not tested an probably incorrect too ;-(
For 8bits mode is this also incorrect?
the first FLEXIO (the IO I need starts at D0)
parallelWidth = FLEXIO_SHIFTCFG_PWIDTH(4); // 8-bit parallel shift width
pinSelect = FLEXIO_SHIFTCTL_PINSEL(0); // Select pins FXIO_D0 through FXIO_D3
the second uses (the IO I need starts at D4)
parallelWidth = FLEXIO_SHIFTCFG_PWIDTH(4); // 8-bit parallel shift width
pinSelect = FLEXIO_SHIFTCTL_PINSEL(4); // Select pins FXIO_D4 through FXIO_D7
I guess you will have to change the clock divider to add 64 pixels left and right.
I am very curious now...
Again, I must have been very lucky with the 352x480 mode...
I think it is time to use a scope to verify all those signals....
May be they are just all wrong...
I also found that changing CPU clock was making everything wrong.
I was expecting the PLL used for the shift register to be independent...
You have to set the PLL that output the pixels , vsynch , hsync at closest you can from 25.175Mhz to get the perfect timing.
1 : Do this 480 times : Output the 640 pixels , then , after waiting the time it need for 16 pixels (H front porch) , you put hsync signal to 0 , now after waiting the time for 96 pixels (H sync pulse) , you put hsync back to 1 and wait again the time it need for 48 pixels (H back porch).
2 : After this wait the time it need to write 10 lines (V front porch) , you put Vsync to 0 , wait the time it need to write 2 line (V sync pulse) , put Vsync back to 1 , wait the time it need for write 48 lines (V back porch).
3 : return to 1 ;)
If you apply this timing , you no more need ... luck ... ;)
Cheers.
About the FlexIO shift width register...
FlexIO only has 1,2,4,8,16, and 32 bit shift modes.
FLEXIO_SHIFTCFG_PWIDTH(x) configures for x+1 parallel output bits, and the shifter mode is the smallest power of two that greater than or equal to x+1. So PWIDTH(5) is 8 bit mode, but PWIDTH(8) is 16 bit mode and PWIDTH(16) is 32 bit mode.
The difference between PWIDTH(4) and PWIDTH(5) is that either 5 or 6 consecutive bits are enabled inside the FlexIO peripheral, but the shifter still shifts by 8 bits each trigger. The extra bits are discarded.
Hope that helps!
Hi,
Thanks for you clarifications!
So at least 8bits colors mode FLEXIO is correct then. 12bits will have to be adapted and tested.
I pushed the code of the emulator with USB keyboard support (QWERTY, at least relevant basic keys)
I will try to focus on the VGA aspect the coming days ;-)
Great news for the USB KB :)
If you tell me where you do the decoding for USA QWERTY KB to Amiga KB , i will add the AZERTY French one (so i can use mine;) )
I have try to understand how the timing , FlexIO and DMA work on teensy , but a little too hard for me who just know this MCU for at least 10 days ..
But in looking on how the other do i will learn faster :)
Cheers.
Actually my keyboard is also AZERTY but somehow the USB library decodes it as QWERTY (a sends q...) ;-) Not sure what occurs with a real qwerty keyboard, I guess that table works.
May be there is a method to configure keyboard1 in emu_api.cpp as qwerty/azerty in the init?
USB keyboard callback ends up in emu_KeyboardOnUp() and emu_KeyboardOnDown() in UAE.cpp
The code commented out there is printing the key from the USB lib.
keyboardAsciiConv table convert codes <= 0x7f to amiga codes (in keyboard.h)
keyboardSpecialConv table converts codes between 0xc0 and 0xdf.
You could add a #define param in platform_config.h for AZERTY/ QUERTY and make another table for AZERTY then?
You can also add all amiga keys of the keyboard.h if you want.
I forgot to mentioned that I get the keys as in the usbhost36 Mouse example library.
I use the main callbacks as I am not interested in the special keys as Volume control...
The keys I get looks like ascii codes (and special codes for F1-F10) if you look at the keyboard USB lib and not really keycodes.
I am not familiar with USB HID keyboard.
Maybe there is a way to know if the keyboard is AZERTY or QWERTY using USB lib?
https://github.com/PaulStoffregen/USBHost_t36
Press A,Q,W on azerty KB if you get Q,A,Z ... then you need FR conversion , not hard to do , i'm on it ..
I have do FR , DE , IT , ES keyboard for the Maximite in 2012/2013 and i do the same on Maximite 2 actually :D
But , i just see that my USB OTG don't have 5v on the T4.1 ... do you know why ?
PS : i tested on 2 different T4.1 board ... no 5v on the OTG
Teensy4.1 has just standard USB, not OTG.
You just solder the connector (header pins) on top of the Teensy (close to the mini USB). 5 wires (2 gnd)
. 5 volt is there too!
https://www.pjrc.com/teensy-4-1-released/
My bad , i say OTG but it's USB HOST :)
The 5v is not active on the pin , on the schematic i see i'ts something to do with USB_VBUS pin from the MCU
Now on KB i followed the files to see where it go , all country are still done in this file :
It's an #include to this file in :Code:C:\Program Files (x86)\Arduino\hardware\teensy\avr\cores\teensy4\keylayouts.h
The only thing to do is uncoment your language #define in start of keylayouts.hCode:C:\Program Files (x86)\Arduino\hardware\teensy\avr\libraries\USBHost_t36\keyboard.cpp
I go to try to activate the FR KB , it can be that USB_VBUS is set only if something is active in the USB lib ...