-
Button Handler Class in Micropython
08/13/2024 at 16:23 • 0 commentsThis Micropython class handles a single button and provides two possible events: Pulse and Long press. It also provides debouncing.
The .event( ) method shall be called at every execution cycle. The constants for debouncing and Long Press thresholds must be proportional to the timing desired. In the example the function is called every 5 ms. Any pulse that lasts less than 50ms is considered as a bounce and hence discarded. If the button is held for more than 500ms the function returns a single LONG press event.
Finally, if the button is pulsed within a time 50ms< t < 100ms the function returns a PULSE
The function can be experimented here : https://wokwi.com/projects/406121126820955137
from machine import Pin, import time print("Button Handler Class") class buttonHandler: def __init__(self,pin): self.pin = Pin (pin, Pin.IN, Pin.PULL_UP) self.tOn = 0 self.tmp = 0 self.evnt = None def event(self): if self.pin(): if (self.tOn <10): # does the key get pressed for at least 10 scans ? self.tOn=0 # no, it was just a bounce, ignore return None else: self.tmp=self.tOn # yes, save amount of scans self.tOn = 0 # and reset counter if (self.tmp < 100): # does the key get pressed for less than 100 scans ? return 1 # yes, it was a pulse else: if (self.tOn < 500): self.tOn = self.tOn + 1 # restrict max value, just in case if self.tOn == 100: return 2 # return long only once return None b = buttonHandler (12) # instantiate and init pin while 1: bte = b.event() if (bte): if (bte==1): print ("short") elif (bte==2): print ("long") time.sleep_ms(5)
-
Normalizing LDR reading
07/01/2023 at 04:12 • 0 commentsAn LDR's resistance, RLDR can vary from about 100Ω in the sun light, to over 10MΩ in absolute darkness (source).
For practical uses we can consider one order of magnitude above and below the extremes, which in numbers means a resistance variation range from 1KΩ to 1MΩ.
With that in mind it is possible to use the LDR along a voltage divider circuit and calculate the values of the resistors so the output voltage will match a desired range as long as such range is reasonably within the voltage rails, for instance, In a recent project I needed to use the LDR reading from an 8 bit ADC to drive a 5 bit soft PWM, then a range of 128 counts could be easily shifted right to get me the values from 0 to 31 (and avoid a floating point division math).
We have then 2 unknown variables, R1 and R2 and two known resistance values and their expected output:
- LDR in dark, R = 1MΩ, Vout = Vdark
- LDR in brightness, R = 1kΩ, Vout = Vbright
It is reasonable to consider that Vdark and Vbright will be symmetrical around Vcc/2, and to perform the calculation of the resistors we can normalize the voltage value to the resolution of the ADC (e.g. use a value of 256 in the math instead of 5V).
Rewriting the terms, considering the half of the ADC scale is 128 and half of the desired range is 64:
- LDR in dark, R = 1MΩ, ADCount = 128 + 64 = 192
- LDR in brightness, R = 1kΩ, ADCount = 128 -64 = 64
That can be solved using the voltage divider equation:
- ADCcount = ADCrange * R2 / ( R2 + R1//Rldr )
Along with the parallel resistance equation
- 1/Req = (1 / Rldr) + (1 / R1)
Combining both:
- ADCCount = ADCrange * R2 / { R2 + [ 1/ ( 1/Rldr + 1/R1 ) ] }
There are several ways to perform the math, including Wolfram Alpha, and the equation to find the resistances can be calculated using the following string
(64+128)=256*(r2)/(r2+(1/(1/1000+1/r1))); (128-64)=256*(r2)/(r2+(1/(1/1000000+1/r1)))
The calculated values will hardly be an exact value, but the E24 series can provide values close enough to get the desired counts from the ADC
Resistor Calculated Value Closest E24 Value R1 ~8072Ω 8K2 Ω R2 ~2669Ω 2K7 Ω It is possible to use the Falstad online simulator to check how good the picked values are, and of course to fiddle with the values. To save time it is possible to use the link below the access the simulation.
INotice that the Vcc voltage was set to 256 to make it easy to check the ADC count values from the LDR in brightness (left) and in darkness (right). The difference between readings is shown in the middle. Also notice the E24 series values provided good results (no need to use precision resistors)
Epilogue:
if the LDR is exposed under extreme conditions the resistance values canreach the maximum values and the voltage range will differ from the calculated, therefore it is necessary to limit the range in software. It will also be necessary to subtract the value from the minimum expected value to have a light reading value starting from 0 (zero).
#define VMAX 192 #define VMIN 64 ... tempValue= adcRead( LDR_CHANNEL); if (tempValue > VMAX) lightValue = VMAX; if (tempValue < VMIN) lightValue = VMIN; lightOutput = tempValue - VMIN; ...
In my case specifically all that's left to do to call it a day is to shift right the light output value to have the Toff within the 0-32 range.
tOFF = lightOutput >> 2;
-
Ninja Tap patch for Rock'N'Roller (MSX1)
03/17/2023 at 04:33 • 0 commentsAfter a suggestion from [gdx] from MRC I took a look at the Rock'N'Roller (MSX1) and started to work on a patch for Ninja/Shinobi Tap multi controller adapter.
First step was to disassemble the game and figure out how the game deals with the controls. There are several calls to 3 of the BIOS routines that read the keyboard, the joysticks and the trigger buttons (from the joysticks) and decided that the best strategy was to emulate such BIOS routines and return correspondent values based on the buttons pressed on the controllers plugged in the multitap adapter.
Next step was to figure out a position in RAM out of the game execution to place the patch code -> address 0xdf00 to 0xe300 seemed nice
Following I have created the alternate routines:
- ALT_SNSMAT
- ALT_GTSTCK
- ALT_GTTRIG
The alternate routines fall back to the original BIOS call when the Ninja/Shinobi tap is not detected (a flag is reset) . for instance...
ALT_GTSTCK: ld b,a ; save row number ld a,(ninjaDetectFlag) ; test for ninja presence and a ; ld a,b ; restore row number jp z,0d5h ; (GTSTCK) ; if not present continue with BIOS routine ; ; read and return STICK value ...
Next step was to generate a list of addresses where the BIOS calls are called and write a quick and dirt and code to replace such calls with the alternate routines created. The +1 is the offset for the instruction code CD (call) at the addresses that call the bios routines.
; Patch Original game code ld hl, ALT_SNSMAT ; patch calls to 0141h (SNSMAT) ld (09648h+1),hl ld (0966bh+1),hl ld (09676h+1),hl ld (09685h+1),hl ld (09b7ch+1),hl ...
Then I have created a function that will be called in the game main loop to scan the joystick ports and detect the presence of a multitap adapter om port A. If an adapter is detected, a flag is marked and the four taps are read and converted as a mirror of a keyboard matrix and joystick directionals and triggers.NINJAPATCH: ; check for presence of Tap call CHECKTAPS ; c = 0 0 0 0 a1 a0 b1 b0 cpl ; c = 1 1 1 1 /a1 /a0 /b1 /b0 and 08h ; isolate bit a1 -> a = 0 0 0 0 /a1 0 0 0 ld (ninjaDetectFlag),a ; /a1 should be 1 if a ninja or shinobi is detected ret z ; scan taps ; ld de,0fa7ah ; Tap connected to joy port 2 ld de,0ba3ah ; Tap connected to joy port 1 ld hl,ntapData call GETNIN ; read TAPS on port 1 ; process taps ************************************* ...
Button Mapping
Tap 1 is mapped as :
- Up, Down, Left, Right -> Ditto
- Trigger A - Z
- Trigger B - X
- Select - SEL
- Start - Escape
That was done to allow full access and control of Options menu from the game, but it is still possible to access and control the Optiosn menu using the MSX keyboard.
Tap 2 is mapped as the QSCS (Q, S, Control, Shift) controls
Tap 3 is mapped as Joystick 1
Tap 4 is mapped as Joystick 2
To be continued... -
Keyboard Controller with Joystick for MSX (2)
11/26/2022 at 21:33 • 0 commentsAdded a second diode to enhance the detection
And drafted some driver code that provides scan and decode that takes 98 bytes plus 5 RAM addresses.
; Scan Atari keyboard and single button joystick using ; and adapter with 74LS139 ; PSG IO addresses PSGAD: EQU 0A0H PSGWR: EQU 0A1H PSGRD: EQU 0A2H ; DetectKB2600 - Detect Atari controller keyboard ; Input: ; register A: 0=Connector 1, >0=Connector 2. ; Ouptut: ; Z -> keyboard detected ; NZ -> keyboard adapter not detected DetectKB2600: call ScanKB2600 ld de,KBROWS ld c,0 Detct0: ld a,(de) and 00010000b ; isolate bit 4 rla or c ld c,a inc de djnz Detct0 cp 01000000b ret ; ; ScanKB2600 - Scan Atari controller keyboard ; ; Inputs: ; register A: 0=Connector 1, >0=Connector 2. ; Ouptuts : bit 7 6 5 4 3 2 1 0 ; KBROWS -> 1 1 1 0 # 9 6 3 ; KBROWS + 1 -> 1 1 1 1 0 8 5 2 ; KBROWS + 2 -> 1 1 1 0 * 7 4 1 ;(JOYTBITS) KBROWS + 3 -> 1 1 1 TA RG LF DW UP ScanKB2600: ; set zero flag according to port option and a ; Save PSG Context ld a,15 out (PSGAD),a in a,(PSGRD) ld (SAVPSG),a ld hl, KBROWS ; Select Joystick port accordingly jr NZ, ScanCon2 ScanCon1: and 10101101b ; clear bit 6 -> Joysel -> joy port 0, 4:PULSE and 1:TRIGGER B ; a = pins 8,7 low (row 0) ld b,a ; a = pin 8=0, pin 7=0 (row 0) set 4,b ; b = pin 8=1, pin 7=0 (row 1) ld c,b ; set 1,c ; c = pin 8=1, pin 7=1 (row 2) ld d,a ; a = pin 8=0, pin 7=0 (row 0) set 1,d ; b = pin 8=0, pin 7=1 (Joystick) jr ScanRow0 ScanCon2: and 10010111b ; clear bit 5:PULSE and 3:TRIGGER B set 6,a ; Set bit 6 -> Joysel -> joy port 1 ld b,a ; a = pin 8=0, pin 7=0 (row 0) set 5,b ; b = pin 8=1, pin 7=0 (row 1) ld c,b ; set 3,c ; c = pin 8=1, pin 7=1 (row 2) ld d,a ; a = pin 8=0, pin 7=0 (row 0) set 3,d ; b = pin 8=0, pin 7=1 (Joystick) ScanRow0: ld e,a call SaveRow ScanRow1: ld e,b call SaveRow ScanRow2: ld e,c call SaveRow ScanJoy: ld e,d call SaveRow RestorePSG: ld e,(hl) ; hl now points to SAVPSG SaveRow: di ; disable interrupts ld a,15 out (PSGAD),a ld a, e out (PSGWR),a ; update register 15 ld a,14 out (PSGAD),a ; select register 14 in a,(PSGRD) ; read keys hhhh*741 or 11110000b ; mask unused bits ld (HL),a ; save keyboard state inc hl ei ret ; Variables ; keyboard rows HHHL#963, HHHH0852, HHHL*741 KBROWS: DS 3 JOYBITS: DS 1 ; PSG register 15 save state during execution, destroyed buttons at the end ; must be contiguous to Joybits SAVPSG: DS 1
-
Keyboard Controller with Joystick for MSX
11/19/2022 at 10:49 • 0 commentsI have built the Atari 2600 controller keyboard DIY to develop an adapter and write a driver for MSX. The adapter aimed for simplicity but it does not provide any detection feature, requiring the user to without an action, either pressing a key or move the joystick to any direction, depending upon the peripheral connected on the joystick port.
If I give up the simplicity and add an Integrated Circuit and a bunch of diodes it is possible, though, to build an adapter that can support both the keyboard controller and a single button joystick, connected at the same time, using basically the same driver. And there's more: the joystick can still be read by Basic.
here's the circuit:
The rows of the keyboard connected at X2 are selected by the pins PULSE (8) and TRIGGER_B(7) (which is bidirectional). The default state of these pins are PULSE->0 and TRIGGER_B->1 which selects the common line of the joystick, thus allowing the single button joystick connected to X3 to be read using BASIC.
Detection is possible by Selecting the third keyboard ROW, then diode D5 will bring down the level on the TRIGGER_A line. The other keyboard rows will keep this line high.
-
Patching Muhonmourn 3 (2)
11/15/2022 at 03:12 • 0 commentsMaking a Cartridge version of the game
I have created a ROM version of Muhonmourn3. It was necessary to move the game to RAM because the game uses contiguous areas to store data (and some areas beyond 0xd400 too).
Additionally, it was required another routine to switch back page 1 from the Game ROM slot to the same slot of the BIOS, otherwise the game ran erratically (slowed down and missing time counter and player counters).
The ROM -> RAM loader is very primitive but it seems to be working fine in many emulated machines.
The loader executes the following steps:
- Check if the computer has enough RAM to load the game
- Load a Splash Screen (or a NO RAM screen advice)
- Copy patch code (from page 1) to RAM segment E000-E1F0
- Copy game code (from page 1) to RAM segment c000-d400
- Copy game code (from page 2) to RAM segment 8000-bfff using RDSLT
- copy page switch code (from page 1) to RAM segment E1F0
- switch page 1 to the same slot that is BIOS ROM
- Jump to game start at RAM 0x915f
The patch was modified to change the text on the screen accordingly with the Ninja Tap presence:
The whole repository can be found at my github page, and here's the link for downloading the ROM image.
Splash Screen
The ROM loader adds about 2 seconds to the startup of the machine running the game, then a Splash screen was added to divert the attention and reduce the perception of the loading time.
The Splash screen uses Screen 3 multi-color mode, with a resolution of 64 x 48 pixels. The image was edited using mspaint and the space color was reduced to 16 colors indexed mode (bitmap) using irfanview, then a python script to convert the pixel information into data to be included on the loader code.
The screen 3 mode uses 1 byte to represent the color of two pixels (each nibble is a pixel color). The whole screen takes 1536 bytes which is the half of 64 x 48 -> 3072 pixels available.
The pixel addressing is not linear but with a bit of observation it is possible to assign the values of the coordinates X and Y to certain bits on a linear addressing word:
def getCoords ( linearCount ): # bit order Y5 Y4 Y3 X5 - X4 X3 X2 X1 .Y2 Y1 Y0 X0 # x 0 0 0 1 1 1 1 1 0 0 0 1 # y 1 1 1 0 0 0 0 0 1 1 1 0 cx = ( (linearCount & 0x1f0) >> 3) + ( linearCount & 0x01 ) cy = ( (linearCount & 0xe00) >> 6) + ( (linearCount & 0x0e) >> 1) return cx,cy
The color translation was done kinda manually, assigning the the indexes informed by clicking on the image opened on Irfanview to the desired MSX color.def translateColor (inputColor): #msxCores = [ 1, 3, 7, 9, 11, 14, 15] msxCores = [ 1, 3, 7, 15, 6, 14, 9] if inputColor <= len(msxCores): return msxCores [ inputColor ] else: return 1
The main function iterates over all 3072 pixels, combining every 2 of them and generating the contents for a include file, skipping a line every 32 pixels (16 bytes).
for i in range (0,1536*2,2): x,y = getCoords (i) pp = translateColor ( pixels [x,y] ) # get MSB color x,y = getCoords (i+1) ss = translateColor ( pixels [x,y] ) # get LSB color bb = (pp<<4 | ss ) & 0xff if (i % 32 == 0 ): outputBuffer = outputBuffer + "\n db " else: outputBuffer = outputBuffer + ', ' outputBuffer = outputBuffer + intToHexValue2digits (bb, '$') print (outputBuffer)
At the end the result is printed on the terminal and can be copied and pasted on a text editor.
It is a very crude script but it was enough for me. It is impressive what we can do with 40 lines of python ( nevermind the blank lines and comments)
Screenshots
The splash screen depends upon the slot where the ROM is inserted is even or odd. Both were inspired in Rock Bands.
As it was mentioned before, the game needs at least 32K of RAM to be copied to memory. On some machines without RAM expansion the No RAM splash screen is shown
Worth to mention that after the splash screen was added it was necessary to add 3 more seconds of delay...
Read more -
Patching Muhonmourn 3
11/05/2022 at 19:59 • 0 commentsThe game Muhonmourn 3 is a multiplayer game developed developed by [hoge1e3] as an entry to MSXDev22 contest. The game allows up to 4 players, being two on keyboard (using arrow keys and WASD) and two on the joystick ports.
The game dynamics is simple but very addictive. On every match you have 60 seconds to control your player to cover as many ground as you can during 60 seconds.
I wish this kind of game existed when I was young, on the occasion when we, our brothers and friends get together to play video-games.
Today this is a game that is perfect for retro meetings and that was my motivation to research about the obscure peripheral named Ninja Tap that allows to use up to 4 joysticks by port, in other words a multi-tap adapter.
At the beginning there was no much information about this peripheral, and I have started to look for information on how to reproduce such peripheral and find out how it works and how to write software for it. The whole story is on a series of pages here in hackaday.io (btw, thanks [Jipe] and [aoineko] )
- Investigating the Ninja Tap: Part 1, Part 2, Part 3, Part 4, Part 5, Part 6
- Shinobi Tap: A sidekick project Part1, Part 2, Part3
Also there's two (long) threads about the device:
Now the Ninja Tap is not an obscure peripheral anymore. It is being reproduced by a user from MSXVillage.
And there is also my Shinobi Tap prototype for "generic" NES controllers with DE-9,
Note: Both Shinobi Tap and an extended version of Ninja Tap named Ninja Towns are available at github in eagle 7 format.Developing the patch
Having unearthed the peripheral now it is time to get back to the software side and build the patch
Disassembly
The first step to make the patch was to disassemble the game which is available at the MSXDev22 page. Oh, and it is possible to play online using a web emulator.
The game is a binary that is loaded from address 0x8000 up to the 0xD397. I have used inkland's dz80 to do the disassembly.
Next steps were to find references for the BIOS routines that read the keyboard and the joysticks.
- SNSMAT 0x0141 Read row of keyboard matrix
- GTSTCK 0x00D5 Get joystick status
- GTTRIG 0x00D8 Get trigger status
Some games may also read the controllers directly using the Z80 instructions IN and OUT (that was not the case).
It was found a function starting at 0x865c that reads the eleven rows of the keyboard matrix using SNSMAT routine. The readings are inverted so a pressed key is represented by a "1".
Then the game reads both both joystick ports using GTSTCK and GTTRIG. The directionals are used on a table entry to convert the value read from bios in the range 0..8 to the four upper bits representing each directional with active level in "1". Then the triggers A and B are added to the bits 0 and 1 respectively. The position of these bits corresponds to the row Y8 of the keyboard matrix.
The scan is stored into 13 consecutive bytes starting at 0x86b9
The Patch
The patch code consists of a jump to a function placed after the main game code that perform the following steps
- Check the presence of a Ninja/Shinobi Tap on joystick port 1 ( only port 1 to simplify the code)
- Return to execute original code if a tap is not detected, otherwise..
- Read the Taps
- Convert Tap 1 data to "RG DW UP LF 0 0 TB TA" and store at 0x86c1 (row 8)
- Convert Tap 3 data to "RG DW UP LF 0 0 TB TA" and store at 0x86c4 (Joystick 1)
- Convert Tap 4 data to "RG DW UP LF 0 0 TB TA" and store at 0x86c5 (Joystick 2)
Get Tap 2 data an fulfill WASD positions at keyboard rows rows 2, 3 and 5
finally return to the game.
The full code is available at Github.
Troubleshooting
During the debugging it was...
Read more -
Shinobi Tap (3)
10/12/2022 at 17:45 • 0 commentsFinally managed to fit the circuit into the case. It was not even necessary to attach the board to the case using the standoffs.
Updated the Schematics and uploaded all to github page.
-
Shinobi Tap (2)
10/11/2022 at 04:45 • 0 commentsI have assembled a prototype for the shinobi tap and during the tests I came across a tricky problem: One of the famiclone controllers worked erratically when connected on position 1. All wiring was checked twice and it was OK.
Exchanged the port where the interface was connected and same results. Exchanged data wires from controllers 1 and 2 and same results.
Observing the waveform on a scope it was noticed that the voltage briefly dropped when a button was pressed, instead of keeping low until the next clock pulse.
A closer observation on the waveform at the moment of a button press revealed the culprit: A short surge that happens when the voltage drops at the output and makes the clock ring. The same effect occurs with both controllers but only one of interpreted this as an extra clock.
On the other ports the ringing is barely noticed.
I was suspecting that the ringing was happening only on port 1 because of the proximity with a low impedance source (the electrolytic capacitor at the input). but some tests I have done later proved I was wrong.
I have tried without success:
- Added some capacitance to the Vcc line.
- Replace the VCC jumper wire with an inductor
- Added a 100 Ohms termination resistor on the pin 4 of the Port 1 (CLOCK)
- Add some resistance in series with the CLOCK out pin (3) of the HCT00
Later I noticed the the other controller (that works despite the ringing) produces the ringing when connected to ports 1 and 2 but not when connected to 3 and 4.
Another thing I have noticed is that when more than one controller had the same button pressed, the ringing was deeper and last a little longer.
Added a 100nf capacitor (value picked at random ) between CLOCK and the ground. This time the ringing disappear and the circuit worked despite the clock signals turned into triangles.
Then I have analyzed again the width of the clock pulse and the duration of the ringing to determine an RC constant to be added between the HC00 and the CLOCK line. The Clock signal takes 6us and the surge around 250ns.
Then I pick a 68 Ohm resistor and a 10nf capacitor to have a time constant of around 680us and added to the circuit, and now the ringing completely disappeared.
Wafeform of the ringing free clock signal
Picture of a full capture
Pictures of the setup
Some screens during test
And a closer picture of the prototype. Notice the 10nf ceramic capacitor at the left of the HCT00.
The resistor is under the board.
-
Shinobi Tap
10/08/2022 at 05:05 • 0 commentsMade some experiments with the circuit, and routed a PCB for use with cheap NES controller clones with DE-9 connectors.
The PCB is single sided and needs a lot of jumpers but nevermind, this is just a prototype. It was routed to fit into a CP-011 box.
During the tests it was noticed that the DATA lines need pullup resistors and they were added to the circuit.
Btw, this is the pinout of the famiclone controllers that I have. I believe most of the famiclone controller follows the same layout.
-
Investigating the Ninja Tap(6)
10/06/2022 at 04:41 • 0 commentsWorked on a modular PCB for a Ninja Tap with FM-Towns controller compatibility. The name of such interface could not be other than..
Ninja-Towns
Schematic
A preview of the PCB (couldn't resist to google for "ninja town" and found something to "inspire" the logo and the ninja character.
Two boards should be stacked and the jumpers should be done on the upper board which is custom made for an off the shelf PB-203 box.
-
Investigating the Ninja Tap(5)
10/06/2022 at 04:02 • 0 commentsGot some time today to investigate the behavior of the original circuit, as well as the fix I have proposed.
I don't have one ACT chip, unfortunately, only got my hands on a 74'00 from HC, HCT and LS families.
Used the s_ntap program by Guillaume 'Aoineko' from MRC.As predicted neither one of the three chips is beefy enough to win the fight against the open collector gate inside the MSX, and because of that the software can not "see" on pin 7 the inverted output from the signal on pin 8.
Then I patched the software to keep pin 7 high during the detection routine.
It takes two bytes on CKNTAP function and one byte at CHECK function.
CKNTAP: di ld b, #0 ; b=Max Player ld de, #0xBF0A ;#0xBF00 <-Here call CHECK ; Port1 Check ld c, a ld e, #0x4A ; #0x40 <-Here call CHECK ; Port2 Check rlca or c .... .... CHECK: call PORSEL inc b and #0xCA ; #0xC0 <-Here out (0xA1), a ; 6,8=L 7=H ex af, af' ;' ld a, #14 out (0xA0), a in a, (0xA2) and #0x20 ; 7=H ? ret z .... ....
After that, success..
The program can identify a Ninja-Tap connected with either logic family tested.
And it works with either Ninja Tap or Shinobi Tap feedback loop
Here's the photo of the setup:
-
Investigating the Ninja Tap(4)
09/29/2022 at 13:46 • 0 commentsIt occourred to me that the Ninja Tap can support the extra buttons of a FM-Towns controller with the aid of a decoder at each tap.
The extra buttons of FM towns controllers maps to conditions that will never occur:
SELECT is UP and DOWN at the same time
RUN (START) is LEFT and RIGHT at the same time
Then the following addition to the Ninja Tap circuit could support FM Towns controllers
-
Investigating the Ninja Tap(3)
09/25/2022 at 21:51 • 0 commentsUser Jipe from MRC (and MSX Village) reverse engineered its Ninja Tap adapter to obtain the schematics
https://msxvillage.fr/upload/pccm_ninja_tap.png
Luckly I was on the right track, being the most relevant difference the SI inputs of the 4021 being pulled up instead of down.
The original circuit uses a 74ACT00 chip not only to feedback the inverted state of signal of pin 8 (pulse) but also to drive the 4021 CLK and LATCH signals (maybe this was the main purpose of the '00 chip).
I have found another error on my circuit. but it was due to lack of attention. Pins 6 and 7 on the input ports were inverted, as D7 on the 4021s shall read the signal of Trigger A and D6 should read Trigger B, not the opposite.
The redrawn schematics is show below:
I have also updated the schematics for the Shinobi Tap, but changed the design of the feedback circuitry to avoid contention, and added a second feedback to allow differentiation between Ninja Tap and Shinobi Tap.
Detection can be performed using the expected states. First set pin 7 to High to release the open collector output at this pin.
Pin 6 (Write) Pin 8 (Write) Pin 7 Read, no Tap Pin 7 Read,Ninja Tap Pin 7 Read,Shinobi Tap LOW LOW HIGH HIGH HIGH LOW HIGH HIGH LOW LOW HIGH LOW HIGH HIGH LOW HIGH HIGH HIGH LOW LOW New Shinobi Tap circuit:
-
MSX / Atari 2600 driving controller
09/17/2022 at 21:42 • 0 commentsSketch for the schematics of a driving controller compatible with Atari 2600 and MSX at the same time.
The circuit uses a rotary switch with integrated push button, and one extra button.
The integrated switch for the rotary encoder connects pin 9 (GROUND on MSX) to pin 7 (Trigger B on MSX). The common return for the extra push button and for the rotary switch is on pin 8 (PULSE) that is driven low by BIOS by default.
When used on Atari 2600 the integrated button works as a positive drive the right paddle input, pretty much like the thumb button on the omega race booster grip (or the LEFT button of a 7800 controller).
-
Investigating the Ninja Tap(2)
09/15/2022 at 01:53 • 0 commentsThe schematic of the Ninja Tap presented below is based on the disassembly of the DM System driver.
And I could not resist to draw a Shinobi-Tap replacing the 4021s by NES controllers.
Note the transistor inverter that provide no risk of damaging the MSX port if pin 7 is held down while Pin 8 is flips.
-
Investigating the MSX Ninja-Tap
09/14/2022 at 04:35 • 0 commentsThe Ninja Tap is an adapter that allows to use up to 4 joysticks per MSX port (MSX Wiki).
There is not much information available on such adapter, let alone the schematics.
I wanted to build a clone of such adapter then I have started to disassemble a driver code and translations of japanese documentation available to figure out the connections.Pin MSX
JoystickFunction 6 goes to PARALLEL/!SERIAL of all 4021s 8 goes to CLOCK of all 4021s 7 receives the inverted level of signal from pin 8 (see oddity below) 1 receive the data out from the first tap port 2 receive the data out from the second tap port 3 receive the data out from the third tap port 4 receive the data out from the fourth tap port 5 is the VCC (5 Volts) 9 GND Protocol
The adapter uses four CD4021s to shift in the controller data from the four controllers:
disassembling the GETNIN function :
The sequence for reading the 4021s is the following
0) the sampling start with pin 8 (CLOCK = HIGH) and pin 6 (PARALLEL/!SERIAL = LOW)- pulse (go high, then low) the PARALLEL/!SERIAL line (pin 6). That will latch the input of the keys to the 4021 internal flip flops. Notice that the CD4021 output is already loaded at the Q8 output.
- Pulse (go high, then go low) the CLOCK line (pin 8). (note: If this pin weren't initialized high, the first bit would be missed)
- shift in one data bit from TAP 1 at the UP line (pin1) into register H
- shift in one data bit from TAP 2 at the DOWN line (pin2) into register E
- shift in one data bit from TAP 3 at the LEFT line (pin3) into register D
- shift in one data bit from TAP 4 at the RIGHT line (pin4) into register C
- Repeat steps 2 through 6 for until all 8 bits are read
- Process the data.
The sequence of bits is the same used by NES controllers, being possible to make an adapter that uses 4 NES controllers with only one inverter (which makes me wonder to reuse a JoyMega adapter to create a Ninja Mega Adapter)
Oddity
The adapter was designed to be detectable by the driver, and uses the inverted state of signal at pin 8 which is applied to pin 7. The driver flips the state of pin 8 and check if inversion occurs on pin 8.
The problem is that pin 7 is an open collector and the detection routine pulls this pin down (instead of let it float ) during the detection, which means that the external inverter will have to fight (and win) against the internal 7407 open collector gate, otherwise the detection will fail.
Here's the code
;====================================== ; Connection Check Sub. ; return with B=B+1 if no hardware detected ; otherwise return with B=B+4 if hardwar detected CHECK: CALL PORSEL ; INC B ; B = Max player number + 1 AND 0C0H ; A is state of port 15. OUT (0A1H),A ; 678=L for both joystick ports (!) EX AF,AF' ; save state of Reg15 with all output pins low LD A,14 ; select register 14 OUT (0A0H),A IN A,(0A2H) ; read state of joystick port AND 20H ; 7=H ? return if bit is high (!) (shouldn't be forced high, its being driven low internally ) RET Z ; if return here, A = state of pin 6, and B=B+1 from the function call LD A,15 ; select register 15 OUT (0A0H),A EX AF,AF' ; restore state of Reg15 with all output pins low OR 030H ; make bits 4 and 5 high (pin 8 of both pulse pins) OUT (0A1H),A ; 8=H for both output ports LD A,14 ; select register 14 OUT (0A0H),A IN A,(0A2H) ; read inputs AND 20H ; 7=L ? is pin 7 low JR NZ,CHECK1 ; no, return with A=0 INC A ; Complement bit 0 of register A (read from pin 6) INC B ; B = B+3 INC B INC B RET ; No NTAP CHECK1: XOR A RET
-
Recovering data from old cassetes
09/08/2022 at 02:50 • 4 commentsI have found a collection of tapes that I used with my HB-8000 MSX computer. Among the commercial games and applications there are some that I have coded in BASIC, Assembly or both.
First tried to read the tapes on the real machine and save them on the SD card of my SDMapper, but I the success rate was low.
I tried to record the sound to decode on PC using one of the tools available (SofaCas, Castools) but the hum as quite high due to ground loop between the PC and the tape recorder.
I looked all over my parts for a landline phone transformer with 1:1 without success. The best transformer that I could find was a transformer with 150 Ohms (measured with multimeter) at one of the windings and 2 ohms at the other salvaged from surplus PCBs.
I have tried out the transformer connected to the tape recorder at either side and measured the amplitude with the oscilloscope to determine the turns ratio.
After some measurements I did the math and found a turns ratio of 15:1. It is worth to mention that such figure will turn the 7.5Volts pk-pk produced by the cassette player can produce a voltage of hundreds of Volts at the secondary of the transformer, depending upon which side of the transformer the cassette is connected. When in doubt connect the cassette side to the transformer side with the highest DC resistance.
At the end this is how I have connected the transformer. I have used an stereo plug at the PC side because my sound card did not liked to have one of the channels short-circuited to ground. A couple of jumpers to allow me to select to record in any of the channels or in both at the same time.
I wish I had a transformer with smaller turns ratio, because the 500 mVpp produced were not enough to achieve full scale of the recording, but I could record and decode some programs.
Here are some screenshots of recording using audacity.
And a screenshot of SofaCas running
Some pictures of the device assembled.
A
And a screenshot of one game that I have successfully recovered: "Resta 1" or Peg Solitaire.
-
Atari Keyboard Controller adapter for MSX (3)
08/24/2022 at 22:50 • 0 commentsAnd it worked fine!
Files at Github Repository (link)
-
Atari Keyboard Controller adapter for MSX (2)
08/24/2022 at 03:13 • 0 commentsFor a matter of symmetry and sake of schematic drawing I have rearranged the wiring, so the MSX pin 8, a push-pull output became an open collector with pull-up resistor, then the pins/rows assignment became
ROW / (Keys) MSX Joystick Pin Keyb. Contr. Pin 0 / ( #, 9, 6, 3 ) 8 6 1 / ( 0 , 8, 5, 2 ) 6 9 2 / ( *, 7, 4, 1 ) 7 5 Or in colors, lol!
I have also wrote a "driver" in assembly to perform some tests on an emulator. The code have been optimized in size the most that I could do and now it can read raw key scans from joystick ports 1 and 2.
; PSG IO addresses PSGAD: EQU 0A0H PSGWR: EQU 0A1H PSGRD: EQU 0A2H ORG 09000h ld a,(PORTKB) ; ; Scan keyboard connected at Atari Joystick port ; ; Inputs: ; register A: 0=Connector 1, >0=Connector 2. ScanKB2600: and a ; set zero flag accordingly ; Save PSG Context ld a,15 out (PSGAD),a in a,(PSGRD) ld (SAVPSG),a ld hl, KBROWS ; Select Joystick port accordingly jr NZ, ScanCon2 ScanCon1: and 10111111b ; clear bit 6 (joy port 0) or 00010011b ; set bits 4, 1, and 0 (all rows unset) ld b,a ld c,a res 4,a ; row 0 (pin8) low, rows 1 and 2 (6 and 7) high res 0,b ; row 1 (pin6) low, rows 0 and 2 (7 and 8) high res 1,c ; row 2 (pin7) low, rows 0 and 1 (6 and 8) high jr ScanRow0 ScanCon2: or 01101100b ; set bits 6, 5, 3, and 2 ( joy port 1, all rows unset) ld b,a ld c,a res 5,a ; row 0 (pin8) low, rows 1 and 2 (6 and 7) high res 2,b ; row 1 (pin6) low, rows 0 and 2 (7 and 8) high res 3,c ; row 2 (pin7) low, rows 0 and 1 (6 and 8) high ScanRow0: ld e,a call SaveRow ScanRow1: ld e,b call SaveRow ScanRow2: ld e,c call SaveRow RestorePSG: ld e,(hl) ; hl now points to SAVPSG SaveRow: di ld a,15 out (PSGAD),a ld a, e out (PSGWR),a ; update register 15 ld a,14 out (PSGAD),a ; select register 14 in a,(PSGRD) ; read keys hhhh*741 or 11110000b ; mask unused bits ld (HL),a ; save keyboard state inc hl ei ret ; Variables ; keyboard rows hhhh#963, hhhh0852, hhhh*741 KBROWS: EQU 09800h ; PSG register 15 save state (overwritten at the exit) SAVPSG: EQU 09803h PORTKB : EQU 09804h ; 0 -> connector 0, 255 -> connector 1
-
Atari Keyboard Controller adapter for MSX
08/23/2022 at 00:37 • 0 commentsFollowing up a post from MSX Resource Center, I can think of an adapter to connect the Atari Keyboard Controller adapter on the MSX.
The keyboard can be read by pulling down consecutively the pins 6, 7, and 8 of the joystick port, while keeping the other pins at high, and read the key pressed on the directionals. A key pressed will appear as LOW.
The diode on pin 8 is to simulate an open collector thus preventing a combination of bad code an many keys pressed at the same time. The pins 6, and 7 are already open collectors and does not require the diode.
The external 4k7 resistor may not be necessary,
Just the adapter:
-
BlueSCSI Single Sided PCB (3)
07/17/2022 at 13:38 • 0 commentsShould have started a project, lol but here we are with the last revision of the Single Sided PCB. now only one micro SD socket and two different adapters.
The model of micro SD socket looks like this
The micro SD socket adapter is usually shipped with the header pins out, hence it can be mounted facing up
The SD/MMC card adapter on the other hand is usually shipped with the pins assembles so it must be solded upside down.
-
BlueSCSI Single Sided PCB (2)
07/10/2022 at 11:34 • 0 commentsStill working on the board, added two options for micro sd socked plus two options for a pre-assemble micro-sd module
Sockets
Modules
-
BlueSCSI Single Sided PCB
07/08/2022 at 14:13 • 0 commentsWorking with a friend on a Single Sided PCB for the BlueSCSI hard drive emulator.
Schematics have been redrawn on Eagle. Added USB fix resistor for Blue Pill, used 2 different footprints for the Micro SD card.
Uses the form factor of a 4 inch bay hard disk.
-
Repository of PCB footprints for Standard Plastic Boxes
07/02/2022 at 05:22 • 0 commentsI have gathered some PCB footprints I have designed into a github repository:
https://github.com/Danjovic/PlasticBoxesPCBs
Most of the PCBs have been drawn using LibreCad and imported in Eagle using the import-dxf.ulp script.
The Case outline is drawn from the manufacturer's datasheets. Then I use the (draw) Parallel line and set the distance to 1 (mm) to draw the PCB outline around the external walls and standoffs and save the file as DXF 2007.
When I run the script I left the scale at 1, and use the same scale I have drawn (mm). As most of the details I have been drawing are on the case outline I choose the tDocu layer as a primary. I usually draw on more than one layer but the importing script merges them.
After loading the DXF I change manually the layers of the board outlines to the tDimension layer. The next step is to put some holes at the desired position.
Same procedure works fine for logotypes too, and it is very nice to trace the bitmaps from Inkscape and use them on eagle, though sometimes the Inkscape generated DXFs don't work.
-
Interrupt driven MSX tape read
12/13/2021 at 23:02 • 0 commentsI've been following athread on MSX.org to add recording functionality to Casduino. So far the tape reading is being done using sampling / signal processing but the real bottleneck seems to be the latency of the SD card writing.
Worth to notice that the same issue happens on the native playback function and such issue was worked around using an interrupt based playback engine.
Then I though why not use the same approach for the recording ?
I have started to work in the problem, and after reading the code on the BIOS listing altogether with the explanations on the Red Book, I came to an architecture using a state machine to mimic the behavior of some of the cassette routines.
TAPION: Find a header in the cassette and measure the baud rate.
TAPIN: Read a byte from the cassette. Tape is read continuously until a start bit is found. Then read the next eight bits.
The state machine is defined as
typedef enum { _INTERRUPT, // 0 _HEADER_SYNC, // 1 _HEADER_AVERAGE, // 2 _DATA_STARTBIT, // 3 _DATA_DATABITS // 4 } t_rxMachineState;
The resources used are one interrupt pin, programmed to trigger an interrupt at every pin change and the Timer 2 which runs free with a pre-scale set to advance one count at every 8us.
The _HEADER_SYNC state counts pairs of transitions until the difference between 1111 sequential pairs is within 32us (4 counts).
The _HEADER_AVERAGE state counts 512 single transitions to determine the average length of a full bit. The parameters LOWLIMIT and MAXBITLEN are defined as 25% around the average (MEDIA)
The _DATA_STARTBIT state add the time taken by sequential transitions until the sum is larger than LOWLIMT, which marks a transition from the last quarter cycle of a "1" bit to the first half of the "0" bit (the start bit). After that the second half of the Start Bit is read.
The _DATA_DATABITS was a tricky one to write (but not as tricky to make it work as the previous state). On the MSX the Z80 counts how many transitions occurred have passed within a given window of time to determine the state of the bit, whilst using interrupts, it is necessary to compare the time taken after you have 2 transitions. If it takes more than a LOWLIMIT, we have a bit 0 and we're happy. Otherwise it is necessary to wait to more cycles and we have a bit 1. After 8 bits, the data is pushed to the stack and the state return to _DATA_STARTBIT. As in real MSX the stop bits are ignored as they are there just to provide some time to process the data read.
Worth to mention that none of the interrupt routines do rely upon the phase of the cassete signal, but soleley on the timing between the transitions.
The _INTERRUPT state is there to take care of unforeseen conditions during the tape reading.
-
MC-10 Schematics Redrawn
09/28/2021 at 03:34 • 0 commentsTandy MC-10 computer schematics redrawn in Eagle. Also available as pdf
Also created a library with specific chips (VDG, 6803, etc)
Files available at GitHub Repository.
-
Add-on for PICKit 2
09/04/2021 at 14:25 • 0 commentsThe PICkit2 programmer provides pull-down the PGC/PGD lines.
As such pull-downs may interfere in the circuit being developed, I have built a simple add-on for the PICKit2 that consists of a dual section switch that disconnects the PGD and PGC lines.
-
Simulating a microphone
04/17/2021 at 16:03 • 0 commentsI was given a microphone spec:
- Vout (RMS) = 0.25mV
- Zout = 9.5 Ohms
And I wish to use an audio generator to simulate such microphone. This can be accomplished by a voltage divider with the right resistor values.
-
Screw Arduino!
12/14/2020 at 12:20 • 2 commentsThis week H-A-D featured an article with a home-built racing sim. While watching the video I have seen that the author did many connections on an Arduino board just inserting the wires on the pin header.
I have seen that before on a considerable amount of projects. It's not something I would rely on for a long term operation circuit, then I realized that there is room for a screw terminal shield. (Eagle Files):
-
Ultimate MSX Caps Lock cartridge
11/23/2020 at 02:21 • 0 commentsThe Expert is a Brazilian manufactured in the 80's and it is compatible with MSX standard. It uses a detachable keyboard but it lacks the Caps Lock LED on the keyboard because the 13 pin connector used ran out of pins (even the shield is used as a 14th conductor for GND).
One day I heard about that issue on my favorite podcast, and just for fun I have designed a Caps Lock cartrige for the Expert. Some time later I have added another feature to the cartridge that is not implemented on the computer: a RESET button.
I have designed PCBs for the MSX cartriges before, like the MSXDOS2 cartride that contains a ROM with the MSXDOS2 kernel with some glue logic to perform the bankswitching (the circuit was not designed by me though). Such cartridge allows the Expert - an MSX1 machine - to run MSXDOS2 without a Memory Mapper.
On this sunday afternoon I have merged the two projects and created the Ultimate MSX Caps Lock cartridge:
The PCB and schematics files are available on Github. I have just routed the board, not assembled the circuit yet, sou use it at your own risk.
-
FM Towns Controller Board Schematic
10/03/2020 at 21:27 • 0 commentsFrom an image posted on msx.org foruns,
the following pinout was obtained:
Button Pin(s) UP 8 DOWN 5 LEFT 6 RIGHT 7 A 2 B 1 SEL 8/5 (through D1) RUN 7/6 (through D2) SW 4 COMMON 3
and the schematic was drawn:
finis!
-
Fixing LG DVD drive
07/13/2020 at 04:20 • 0 commentsA 100% of the CD and DVD drives that I have from LG suffered from an annoying aging problem. After few months of use the CD/DVD fails to load the media and eject the disc. At first it occurs oftenly and gets worse with time up to the point the it fails everytime.
I needed to reinstall the operating sytstem on an old machine and the drive - an LG unit was at the point that it failed all the times.
Then I've took off the covers of the DVD player to figure out what was happenning and I have found that the loading mechanism required good force at the end of its course.
Such mechanism is driven by a belt that I found that was too loose - in the sense that it lacked tension - to provide the necessary friction.
To fix the problem I used a sillicone band torn in two (as it was too wide to fit). Though the perimeter of the sillicone band was much smaller than the original belt, it supported the tensioning very well and it restablished the DVD player.
Worth to mention that the belt can be replaced without openig the drive as the belt is reachable (using a tweezer) with the DVD with its door opened.
-
Dormant Casemod projects
07/10/2020 at 14:37 • 0 commentsA couple of weeks ago I've started to work on some Casemods that have been sleeping for a while.
So far I have completed:
- Megadrive PC
- TankServer
And I am currently working on:
- BattleStation
- RetroSlim
-
Investigating Arkanoid II incompatibility with Digi:Arka
04/27/2020 at 15:47 • 0 commentsBut the user that reported me the problem have the original paddle controller that was bundled with the game and such controller works in both titles (Arkanoid I and II).
Further investigation is necessary...
-
Sidekick project
03/10/2020 at 23:05 • 3 commentsThe idea for this project occurred to me while I was implementing the PC Joystick adapter for #Control Freak , and the user @Dave's Dev Lab mentioned that he had 300 IBM PC jr joysticks and I started to wonder if I could use the cheap Digispark instead of the Arduino Micro.
The PC jr joystick, as most of the early PC controllers provides only a couple of axes and two buttons. In other words only 4 I/Os are necessary and that is exactly what Digispark provides.
I could reuse some of the experience acquired during the development of support for paddles in the Atari adapter for my #AVeRCADE board, as long as I did some work to adapt the "raw" environment of V-USB+GCC to the Arduino "framework" used by Digispark.
First thing done was to synchronize the potentiometer reading to the USB interrupts. That can be achieved by putting the CPU to sleep(), and the timing loop will always run after the CPU wake up to service an interrupt. The header is required though.
Second thing to do is ti turn off Timer1. It took me some time to realize that the Timer 1 (instead of Timer 0) was generating unwanted interrupts, waking the micro controller at the wrong time. Some Arduino functions rely on this timer and therefore will not work, most notably the delay( ) and therefore the Digispark.delay( ).
Main loop code:
void loop() { sleep_enable(); // Prepare CPU to sleep power_timer1_disable(); // turn housekeeping off sleep_cpu(); sleep_disable(); if (++interval > 3) { // run once in row of a three interval = 0; for (i = 0; i < 150; i++); // 100us delay doNewSample(); populateValues(); DigiJoystick.update(); } }
And the result:
... aX=0; aY=0; countVar=255 do { sample = ~PINB; aY += sample & (1 << 0); sample >>= 2; aX += sample & (1 << 0); } while (--countVar); ...
And the result is a counting loop of mere 300us (microseconds)!
The last piece of the puzzle is the calculation of the timing capacitor. The following parameters shall be considered:
Charging time: ~310us
Potentiometer Resistance for maximum charging time: 100k Ohms
Supply Voltage (Vcc): 5Volts
Input threshold voltage: Vih = 2.5Volts
The calculation formula is well knownThe number crushing can be easily done with the aid of Wolfram Alpha
The closest capacitor value is 4.7nF
Buttons
The only two pins left for the buttons are pin 1 and pin 5 and both will require some attention to make them work as button inputs. Refer to the diagram below:On Digispark boards, digital Pin 1 is pulled down by a 1k Ohm resistor (R2) in series with an LED (D2). One option would be to rework the board and remove the LED or the resistor but another option, less invasive is to use a pull up resistor that provides a resulting voltage above Vih (2.5 as we have seen before) . Tests were performed with 1K and 560 Ohms resistors...
Read more -
Digikeyboard with LEDs
03/08/2020 at 20:25 • 4 commentsI have just added support for LED status on Digispark Keyboard library.
Now to get the LED status is just a matter of calling the functionDigiKeyboard.getLEDs()
DigiKeyboard.getLEDs()
and test for one of the 3 contants:
NUM_LOCK
CAPS_LOCK
SCROLL_LOCK
Just like in the example
// USB Caps Lock Led gizmo - Danjovic 2020 // Use modified version of DigiKeyboard library // https://github.com/Danjovic/DigistumpArduino/tree/master/digistump-avr/libraries/DigisparkKeyboard #include "DigiKeyboard.h" void setup() { pinMode(1,OUTPUT); // Digistump BuiltIn LED as output } void loop() { // Check the state of Caps Lock and change led accordingly if (DigiKeyboard.getLEDs() & CAPS_LOCK) digitalWrite(1, HIGH); else digitalWrite(1, LOW); DigiKeyboard.delay(10); }
The modified version of the libraries are available at:
https://github.com/Danjovic/DigistumpArduino/tree/master/digistump-avr/libraries/DigisparkKeyboard
It is necessary to get the 3 files below...
- DigiKeyboard.h
- usbconfig.h
- hidkeys.h
The latter file enhances the keystroke definition of the original project and defines full set of HID Keycodes (from 0x00 to 0xE7).
.. and copy the files to the following pathc:\Users\__name_of_your_user___0\AppData\Local\Arduino15\packages\digistump\hardware\avr\1.6.7\libraries\DigisparkKeyboard\
-
Time precise method to provide analog position to ATari 5200
03/05/2020 at 04:07 • 0 commentsThis is another method for providing analog position to Atari 5200 that does not depend upon internal calibration.
The analog controller information is measured by Pokey chip that measures the time a capacitor takes to increase its voltage from near zero to a given value. This time varies with the resistance of the potentiometer axis.
Many videogames and computers, like ATari 2600, PC gameport, Apple][ gameport usually discharges the capacitors right before start a new reading cycle. On these systems is just a matter of waiting for the capacitors to discharge to know when to push the line high to provide a desired position (timing) information.
But in Atari 5200 that is not so easy because Pokey chip keeps the capacitors discharged by until the next sampling cycle that depends upon the game loo, therefore the discharge moment can not be used as a time reference.
The experiments that I have done consisted in:
- polarize one of the pot inputs with a resistor that provides a low counting, e.g. 10KOhms and detect the voltage increase before it reaches ~1.9V that is the input threshold voltage of POT pins in Pokey Chip.
- Then the line is forced LOW by the time enough to provide the desired counting in Pokey chip.
- Finally the line is pushed high to exceed the threshold voltage and that makes pokey capture the exact counting.
Worth to mention that this method does not depend upon internal calibration of Vac voltage (at pin 9).
The links [1][2] are for two videos with the first experiments. The tests have been performed on a AVR (Arduino board) together with the #Atari 5200 Controller Port Emulator
-
Another Atari 5200 controller adapter concept
01/24/2020 at 04:49 • 0 commentsMegaPlay adapter lets you play Atari 5200 using a 6 button Sega Genesis controller yet providing full keypad control.
The circuit can be built using an Arduino Nano and two analog multiplexers. Interface with analog joystick can be borrowed from "Low Priced MasterPlay clone adapter".
Keypad presses can be emulated by activating a pair of analog multiplexers. This scheme allow the simulation of 1 (one) keypress at a time, but frees the software from critical timing.
Buttons can be mapped as follows:
-
Atari 5200 controller adapters
11/25/2019 at 02:48 • 0 commentsThe Atari 5200 controllers are well known by its low reliability. Many alternatives to the original controllers have rose along the time from when the sytem was being sold on stores up to present days when it is possible to find adapters being produced and sold by members of Atari Age community forums. The adapters found today can be either:
a) analog - based on digital potentiometers or
b) digital - based on switched resistors.
Both change resistance in a RC network that is used by the console to convert a time measurement into positional information.
There are other ways to do it, though:
- Applying a variable voltage on a fixed resistor. The charging time depends upon the RC constant for a given potential difference (voltage). That is pretty much how the trackball works.
- Detecting the moment the timing capacitor start to charge and hold the voltage low until the correct timing has passed. On the 5200 it is a tricky task, because the capacitors do not receive a pulse (of known time) to discharge. Instead they are held discharged until the CPU generates a pulse internally that releases the charge.
I have figured out the methods above after went through plenty of technical information such as datasheets, books and forum posts. In the meantime I have worked on the design of some alternative controller adapters:
Norris: Adapater for Wii Nunchuck controller.
- Provides vertical/horizontal movement plus 2 buttons. - Keypad functions are provided by tactile switches. - Body composed by 3 PCBs stacked on top of each other
- Built-in Wii Nunchuck connector on PCB
- Wire bridges on PCB to hold game faceplates
Hunter: Adapter for Playstation Dualshock controller.
- Provides vertical/horizontal movement plus 2 buttons - Analog sticks can work together or expand to a second connector (for Robotron)
- Directional D-PADs work behave like digital controller on Masterplay adapter
- Numeric Pad emulated by the controller by pressing L2. Worth to mention that emulating the keyboard can be somewhaty tricky too.
- Can emulate behavior of trackball, behaving like the Trackpoint on Thinkpads
Stingray: Adapter for Wii Nunchuck Classic controller
- Basically the same functionality of the Hunter
- Numeric Pad emulated by the controller by pressing ZL
- Built-in Wii Nunchuck connector on PCB
Concept board for StingRay -
Emulating a potentiometer for the Atari 5200
10/28/2019 at 23:30 • 0 commentsSo far the controller adapters I have seen for the Atari 5200 and that can provide analog control use a used a digital potentiomenter (and extra capacitance).
This is certainly a nice solution but there are other alternatives, though:
1) Keep series resistor constant, vary the voltage applied to charge the capactor (just like the trackball do)
That can be done with a PWM providing 0-5V and some resistors in a network to match the desired voltage range. This method is used on the CX-53 trackball.
2) Detect when capacitors start to charge and hold the line down until the desired count, then push the line to +5V
It is a pity that the architecture of the Pokey Chip, used by the Atarti 5200 to read the potentiometers do not discharge the capacitors at the beginning of the sampling cycle but at the end. The only mark of the beginning of the charge is that the voltage over the capacitor starts to ramp up and that can be done by the analog comparator of a microcontroller set to a voltage that is below the minimum Vih (1.9V). Luckly there is plenty of time to react to that, as the pokey counts in Hsync lines (64us ).
-
NES Hypershot Controller Pinout
09/24/2019 at 05:43 • 0 commentsI have acquired recently a Hypershot controller for Famicon model JE506. Such controller comes in a pair and share the DB-15 connector to be attached on expansion port.
Given the state of the buttons I wonder if the previous owners were Wolverine and Sabertooth...
Nevertheless I got some reading on NesDev Wiki that pointed that the Hypershot controllers should be read by the console as single switches instead of a stream of data. Such information were confirmed with a multimeter.
The measurements performed were compared with the information presented on the wiki about the JE506 controller. The results show some difference from the JE506 information presented elsewhere on the wiki, considering the pinout of the expansion port presented elsewhere on the wiki. The Common pins for controllers (Out 1 and Out 2) are exchanged, as well as the JUMP/RUN function for both controllers.
The result of my measurements is depicted below.
-
A closer look at NEWPAD subrom routine
08/27/2019 at 05:26 • 0 commentsAfter spent some time unsuccessfully looking for precise information about the Mouse protocol used by MSX computers I got a subrom binary to disassemble and take a look.
Mouse reading is performed by NEWPAD subroutine at address 0x1ad but the reading effectively occurs after addres 0x3509:
The Mouse routine reads 6 nibbles (0..5) in sequence, cadenced by the (toggling of) pin 8. Small delay loops are inserted between readings. Both the Mouse and the Trackball reset their internal counters after one edge of the Pulse signal.
The 5h nibble read might be the High order nibble for the Mouse or the delta Y value for a trackball.
Given the typical DPI resolution of the MSX mouse no displacement above 16 steps should be observed, then the expected value for the 5th nibble should be 0b0000 for positive displacement or 0b1111 for negative displacement.
The trackball is a much less resolution device and uses solely 4 bits, nevertheless as the mouse only a small amount of displacement should be observed (zero or one count up/down).
One of the curious aspects of the trackball is that it uses an inverted sign bit, which means "0" displacement is represented by 0b1000, and that is the key for the NEWPAD routine to differentiate a trackball from a mouse.
; Nibble 5: Trackball: Delta Y, inverted Sign bit ; (7) 0111 (-1) minus one ; (8) 1000 ( 0) zero ; (9) 1001 (+1) one plus ; ; Mouse: Delta X high nibble, normal sign bit ; ( 0) 0000 ( 0) Zero ; (15) 1111 (-1) Minus one xor 08h ; Turn values 7, 8, 9 into 15, 0 and 1 sub 02h ; Turn 15, 0 and 1 into 13, 14 and 15 cp 0dh ; Trackball should greater or equal 13 jr c,returnMouse ; values less than 13 ; returnTrackBall: ....
The brief positive pulse issued after the 6th nibble is read has the purpose of reset the internal Y counter of a mouse, as registers should be read in pairs (4 nibbles).
-
SMS Paddles on Sinclair ZX computers
07/23/2019 at 04:50 • 0 commentsSinclai ZX computers (ZX81/Spectrum) don't ship with a joystick port but they can count on the ubiquitous Kempston interface to provide 4 directional lines plus 3 buttons and that is more than enough to connect a Sega Master System HPD-200 paddle controller.
Paddle detection and reading code provided by SMS POWER. I/O address changed to match Kempston (0x1F), though.
A simple hardware adapter is necessary in between the Kempston interface and the HPD-200 paddle
An alternative for the HPD-200 is to build a DIY SMS/MarkIII paddle controller by Raphaël Assénat. In such case the wiring can be modified to route the signals from pins 5,7 and 9 thus dispensing the use of the adapter.
Example code (work still in progress) available at my github repository.
-
CP297s
07/02/2019 at 00:37 • 0 commentsPCB for ZX97 lite on a CP200s case. Kicad files available at github
-
Backporch for ZX97 lite
06/21/2019 at 23:24 • 0 commentsI believe it is possible to add a backporch for ZX97 (original) using three available gates from U25.
D11 discharges the capacitor at each negative horizontal pulse coming from /CSYNC and causes pin 11 of IC25 to go LOW, which blanks the video output signal at U25C.
After the sync pulse leaves R4 start to charge the capacitor. While the voltage is below positive threshold of U25 inputs the video stays blank, thus generating the backporch level. After that the output of U25D goes HIGH and the video content coming from U5B pin 8 can reach the output.
It might be necessary to fiddle with the value of R24 according with the technology of U25 (LS, HC, HCT, etc)
The resistors R1,R2,R3 were calculated to provide full compatibility with RS170: 1Vpp @ 75 Ohms load, 70% Video, 30% sync, DC coupling at output (the latter is a de facto standard).
This circuit have not been tested yet on the ZX97 but works like a charm on TK85 (a ZX81 clone)
-
Atari 7800 joypad to MSX Adapter
06/13/2019 at 01:24 • 0 commentsOne of the users at msx.org tech forums asked if was possible to use Atari 7800 joypads in MSX.
The 7800 controllers are very similar to 2600 and therefore to MSX. The main difference is that to maintain compatibility with 2600 joysticks whilst providing two buttons, the 7800 used active high buttons on pins 5 and 9 which are used in 2600 for paddle inputs.
The straightforward solution is to invert the signals and that can be accomplished by a pair of NPN transistors.
Controller and adapter schematics, side by side, for better understanding.
-
Retro Prototyping Board
05/16/2019 at 04:50 • 0 commentsPCB for prototyping retro computing and gaming projects.
100 mils spacing up to 72 vias edge connector, 36x28 (1008) vias prototyping area.
Available for download or order at oshpark
-
SD2IEC board
06/12/2018 at 19:36 • 0 commentsMy version of PCB for "SD2IEC Revisited" from Retrohax (https://www.retrohax.net/sd2iec-revisited/).
Hand routed, has basically the same dimensions and can be even built by tone transfer (no vias under components). -
Tic Tacs
06/08/2018 at 00:43 • 9 commentsMy collection of homemade projects stuffed inside Tic Tac boxes.
-
Random Stuff
04/09/2018 at 10:16 • 0 commentsBottle Openers
Built during a sunday morning out of scrap wood worked with files and sandpaper then finished using wood finishing oil.
-
Ideas for my Linear RGB clock
02/22/2017 at 23:19 • 1 commentInspired by #Linear RGB LED Clockby Jan I decided to build my version. Instead of RGB LED addressable strip I'll be using regular LEDs and shift registers.
As I am planning to use the cheap chinese Digispark boards and a minimal of components. Since RESET pin is not available as I/O in most of the cheap boards I have only 5 pins to spare.
Two pins are for I2C communication with the RTC module
One pin will drive the shift registers using Roman Black's 1 bit shift system
The last two pins will be shared by a button and an LED each. Thus I need only three 8 bit shift registers (74HC595) for driving the remaining 24 LEDs
here's the draft for the circuit.
-
ZORKDuino Shield
02/14/2017 at 18:38 • 0 commentsBrowsing had.io pages I've stepped on the amazing #Zorkduino project wich implements a Z-Machine to play text adventure games (like Zork!).
The original project is very cool but it was build upon some ready made modules and a proto-board, so I've decided to route an specific board for the project named ZorkShield.
The board was designed to allow the assembly of both SD or MicroSD card slots and also allow the assembly of either a P2 stereo jack or a dual stacked RCA female for audio and video.
The video output have been slightly modified so the voltage and output impedance follow the RS-170 standard (like #VGA Blinking Lights). As a late time improvement I've added a RESET button.
Despite the board is a double layer It can be etched at home using tone transfer.
The layout was uploaded to OSHPARK but soon I'll upload it to github.
-
AVRs from Microchip... mindblowing!
01/18/2017 at 16:07 • 3 commentsToday I have received a Microchip news with AVRs on it. That's the first time I ever seen Microchip advertising AVR microcontrollers. Despite the acquisition of ATMEL by Microchip is old news now this ad still blows my mind, lol!!!
-
Single Sided
12/01/2016 at 21:28 • 3 commentsAfter reading this post from @Radomir Dopieralski I couldn't help the challenge and completed the single sided version of the #Servo Breakout for WeMos D1 Mini board.
UPDATE: 3V/5V selection
-
Making boards for projects
11/27/2016 at 15:05 • 0 comments -
Nyanning, this time for real
11/25/2016 at 00:34 • 2 commentsNow I was able to Nyan!! I have used a 32 Ohm loudspeaker in series with a 220uF capacitor instead of the piezo buzzer.
It was necessary to put a 100nf between the VCC and GND of the microprocessor, otherwise it runs erratically.
Thanks again @Radomir Dopieralski for the board and for the code.
-
Nyanning
11/24/2016 at 11:15 • 3 commentsFinally found some spare time to assemble one of the #Nyan Boards that were kindly sent to me by @Radomir Dopieralski.
The rainbow colors match the original Nyan cat (from red to violet) and I have added a wire for the RESET signal.
Arduino support for Tone does not seem to work on Attiny85, so I am looking for an alternative way to play the sound.
Never gonna give up! Lol!!!!
-
Finished the Retro PC casemod
11/24/2016 at 04:11 • 0 commentsJust finished the assembly of the Retro PC casemod.
Some details can be seen in my blog but here is another video slideshow for the impatient.
-
Retro PC Casemod
11/15/2016 at 01:42 • 0 commentsBased on Dynavision Radical, a Brazilian NES clone manufactured by Dynacom.
Specs:
- Motherboard BAT-TI2 with Celeron J1800 built in
- 8GB DDR3
- 120GB SSD
- Running Xubuntu 16.04 LTS
- Dual Genesis 6 button adapter powered by #AVeRCADE
Still in progress...
-
​Generating video signals on a microcontroller with correct amplitude and impedance.
10/19/2016 at 04:34 • 2 commentsComposite video standard defines a signal with 1Vpp amplitude under a 75 Ohms. From that signal 70% (0.7V) is the amplitude of video information which stands above a 0.3V pedestal, while the synchronism information (sync tip) corresponds to the remaining 30% of the total amplitude or 0.3Volts below the pedestal.
Many projects of video generation for microcontrollers provide video signals that may work but don't respect the video standard, thus the signal generated might not be properly displayed depending upon the monitor used.
But generating a video signal with correct amplitude and impedance can be easily accomplished with the aid of resistors and some math.
Consider the circuit topology below where pin named VBIAS generates Sync signals, while VCOLOR pin generates video signals.
With two pins for generating the Sync and Video information we can have four possible combinations from which only three are expected: Sync level, Black (pedestal) and White Level.
We need then to calculate the value of the resistors wich can provide the following voltages
Black Level 0.3 Volt @ 75 Ohms White Level 1.0 Volt @ 75 Ohms Sync Level 0 Volt @ 75 Ohms
First thing to consider are the Voh and Vol from the microcontroller. Taking a PIC16F688 as example such levels can be in the range from VDD-0.7Volts to Voh and 0.6Volts to Vol. It means that our Sync level might be slightly biased to 0,3Volts under 75 Ohms load (0.6Volts without load).
Our amplitudes must then be corrected to compensate for the biased Sync level while maintaining the total amplitude in 1Vpp
Black Level 0.6 Volt @ 75 Ohms White Level 1.3 Volt @ 75 Ohms Sync Level 0.3 Volt @ 75 Ohms
Considering the resulting internal impedance of 75 ohms such values shall be doubled when no load is present.
Level VSync Vvideo Vout(@75R) Vout(no load) Black 4,7V 0,6V 0,6V 1,2V White 4,7V 4,7V 1,3V 2,6V Sync 0,6V 0,6V 0,3V 0,6V
Now we have the necessary information to calculate the resistors. Let us use Kirchoff's current law: “At any node (junction) in an electrical circuit, the sum of currents flowing into that node is equal to the sum of currents flowing out of that node”
Then we have
Considering the voltages involved we have now the generic circuit equation:
Let us use Conductance instead of Resistance to make the math easier to deal with
Then for RL=75Ohms, VOL=0,6Volts e VOH=4,7Volts (PIC Vdd @ 5,4Volts) the equation for the three possible video levels are:
On the absence of load, RL = infinity, which means the Conductance is zero. Then we have the equations for the unloaded circuit.
The 6 equations can be written as a product of matrices
Using Scilab we can easilly get the resulting conductances.
>A=A={4.1 0 -0.6 ; 3.4 3.4 -1.3 ; 0.3 0.3 -0.3 ; 3.5 -0.6 -1.2 ; 2.1 2.1 -2.6 ; 0 0 -0.6} >b=[ 0.6/75 ; 1.3/75 ; 0.3/75 ; 0 ; 0 ; 0 ] >x=A\b
Which can be converted to resistances, resulting in
>x.^-1
Then using the most close commercial values we have:
Let's now do the oposite way and check which are the theoretical values we can achieve using commercial value resistors. Rewriting the equations in terms of Vout we have:
Then solving for the possible output levels we have:
Level Vsync Vvideo V Out(@75R) V Out (no load) Black 4,7 0,6 0,64 1,29 White 4,7 4,7 1,35 2,71 Sync 0,6 0,6 0,17 0,35
Let us now estimate the
output impedance by the ratio of voltages with and without the 75
Ohms load.
Vopen/Vload = 2,71/1,35 = 2,01
Then from Thèvenin:
In plain numbers we have ri=75 * (1,01) = 75,75 Ohms. Good enough!
The figure below shows the circuit with final values.
For calculating the resistor values for other microcontrollers and logic gates (TTL, CMOS) it is possible to use the general matrix system below. The green lines correspond to the voltage levels with 75Ohms load while the blue lines are the voltages with open circuit (no load).
In Scilab, it is possible to use the equations below:
Voh = 4.7 ...
Read more -
Shorty85
10/15/2016 at 07:52 • 6 commentsI've been porting this the project #Shorty - short circuit finder form @jaromir.sukuba to the ATTiny45/85.
I have been working too on a single sided board for the project. The board takes 3.3" x 0.6" (roughly 84mm x 16mm).
-
Nanite Single Sided V2: Eagle and Kicad
09/26/2016 at 16:23 • 0 commentsFollowing a suggestion from [tekkieneet] to rotate the microcontroller 90 degrees and move the push-button to the right edge of the board I have redesigned the layout this time also using Kicad.
Here are the results
In Eagle
And in Kicad (dimensions in inches only)
-
My Single Face version of Nanite board
09/23/2016 at 22:19 • 0 commentsI've posted a remark on the article "Creating a PCB in Everything" endorsing the design of single sided PCBs for DIY projects since they are far easier to replicate at home using techniques like toner transfer.
I've then started from original Nanite board and designed a single sided board for it, tinier as possible, using only PTH components.