Matrix schakelaar in IC

fatbeard

Honourable Member

Dat keyboard werkt omdat er tijdens de scan-fase altijd maar één adreslijn (=kolom) laag is. Alle toetsen op die kolom worden dan tegelijk uitgelezen door de ULA.

Dit is te simuleren door de kolommen als inputs aan te bieden op een willekeurige µP en dan 5 (open drain!) outputs parallel te schakelen aan de inputs van de ULA. De µP kan zo elke toetscombinatie simuleren.
Voedingsspanning kun je gewoon aftappen van de 5V in de ZXspectrum.

Ik heb dat ooit gedaan met een tweetal TTL chips en een PLD om een volledig toetsenbord aan te sluiten.

Eric was iets sneller...

Een goed begin is geen excuus voor half werk; goed gereedschap trouwens ook niet. Niets is ooit onmogelijk voor hen die het niet hoeven te doen.

De adreslijnen zullen vanuit de CPU gezien enkel uitgangen zijn. De diodes zitten dan op de verwachte plaats. De ULA zijn dan ingangen, voorzien van pullups.

Het is zeker zo dat er een snelheids probleem kan zijn, maar ik zou toch als eerste even een snelle 'Duino of andere microcontroller breakout er aan hangen en kijken of het met PCINT's niet lukt.
Stel dat het goed genoeg werkt, dan scheelt het enorm veel verder ontwikkelen.

[edit]
Sorry, laat.

Op 4 juni 2022 10:49:42 schreef EricP:
Met een controller zie ik nog wel ff 'een dingetje', afhankelijk van hoe rap die spectrum leest na het zetten van het addres.
Ik kan me zomaar voorstellen dat een ULA dat doet en dat er wel een hele clock cyclus tussen zit (maar ik weet het niet...). Als die op 1MHz loopt, dan moet je best rap met je controller zijn

Echte toetsen (het origineel) denderen. Dat duurt rap 10ms, dus die ULA (of de SW erachter) moet daar mee overweg kunnen.

Dus als de 'diuno er een paar klokken langer over doet is niet echt een probleem denk ik. De "onzin" die dan van het toetsenbord komt is gewoon "contactdender".

Qua code zou ik van de in te drukken toets uit gaan: Dat geeft een "bij deze 1-uit-8 waarde" moet "deze 5 bit waarde".
Dan loopen op "ingang = 8 bit waarde", en als true -> 5 bit waarde. Interrupt gebruiken voor de uart, en in de interrupt de 8 en 5 bit waarden aanpassen.

Detail:
Normaliter zou je om een 8x5 matrix uit te lezen maar een van de 8 inputs tegelijk activeren. Maar andere combinaties kan ook, is alleen iets moeilijker decoderen.
Hier zijn die 8 inputs ook je adres-lijnen.
Zou Clive Sinclair hier een Steve Wozniak gedaan hebben en ervoor gezorgd hebben dat de memory refresh het keyboard uitleest?

EricP

mét CE

Leuk, die dender. Maar... Niet zo relevant. Als je zeg 10x per seconde de boel uitleest, dan kun je prima dender weg werken. Ook als je elke keer na het setten van het juiste lijntjes direct naar het resultaat kijkt. Het is asynchroon. Ook als je eerst een lijntje zet en pas 50mS verderop kijkt wat er terug komt, kan die knop net ingedrukt zijn en je midden in de dender zitten. Dat lost dus niks op tov. 'direct' lezen.
Als je met je controller te laat bent, dan komt er gewoon het verkeerde antwoord uit (cq. de 'scan' is al een lijntje verderop en krijgt het antwoord van het lijntje ervoor). Dat gaat hopeloos de mist in.
Een CLPD kan het waarschijnlijk ook wel trouwens. Of neem een kleine FPGA. Dan kun je min of meer je 40 relais in 1 chip emuleren :+

Daar heb je inderdaad wel een punt, die ULA kan verwachten dat de input laag wordt in dezelfde klok-periode als dat ie de adreslijn laag trekt.

Aan de andere kant, je 'duino weet ruim van te voren welke toets je gaat simuleren, en welke adreslijn ('duino input) en ULA-input ('duino' output) daar bij horen.

Dus je 'duino kan spinnen op het input register, en gelijk de output laag maken als de input gezien is. Dat zijn 4 instructies, dus 250ns op een 16MHz AVR. Wat is de klokfrequentie van de ULA?

Ik zou het in ieder geval eerst eens met een MCU uitproberen voordat ik een CPLD of ingewikkelder eraan zou wagen.

(Ook omdat ik verwacht dat de keyboard scan vrij voorspelbaar langskomt, en dus de MCU respons goed te plannen is)

EricP

mét CE

Dat is ongeveer het idee waar ik op doelde. Maar het zijn geen 4 instructies. Zo even uit mijn hoofd 'kost' een interrupt 2 cycles. Zo uit mijn hoofd is er een 'pin change' interrupt. Echter, dat is (wederom uit mijn hoofd) 1 interrupt voor alle pins waarbij je het 'aan' hebt staan. Of soms 2 of 3 (een beetje afhankelijk van de versie van de AVR). Dat betekent dat je je flags moet stacken (1 cycle), je werkregister moet stacken (1 cycle), op moet halen welke lijn de interrupt veroorzaakt (1 cycle), dat moet comparen (1 cycle) en dan wellicht jumpen (1 cycle).
Dan kun je de output setten (dat is voorbereid, maar moet je wel uit RAM halen), dat zijn zomaar 2 tot 4 cycles. Dan 2x wat van stack halen (2 cycles) en een return (2 cycles). Dat is zomaar een cycle of 15. Daarnaast komt die interrupt uiteraard op een moment dat je net een clock tick gehad hebt en een dual-cycle instructie loopt, dus dat worden er 17. Je kunt immers alleen maar interrupten tussen instructies. En dan zou het zomaar kunnen dat ik er nog eentje vergeten ben.
Welnu, op 20MHz ben je dan dus zomaar vrijwel 1μS onder water. Dus zelfs als die ALU op de ene clock tick de boel set en op de volgende uitleest, houdt het niet over. Als het ding op de rising edge address set en op de falling edge leest, dan ben je botweg te laat. Zelfs als je de tijd voor een 'unwrap' van je routine eraf haalt, is het erg tricky.

Je zou in je AVR nog wat met polling kunnen doen: kijken continu kijken naar het address (get, compare, jump-if-not-what-we-need, set output, jump to get). Dan ben je sneller. Dan moet je alleen wel ff nadenken hoe je de waarde die je wilt outputten gaat setten. Dat zou je nog met iets interrupt-drivens kunnen doen (en in de loop de interrupts uit zetten). Maar daar moet je goed over nadenken: mis je een scan, dan is er niks aan de hand. Maar als je halverwege een scan uit de ISR komt, dan zou je wel weer eens te laat kunnen zijn.
Ook dat is wel weer oplosbaar, maar het begint zo zachtjes aan wel op hogere wiskunde en diepere kennis van een controller te lijken.
Je zou een soort van moeten gaan tellen of je alle 8 lijntjes gehad hebt en dan heb je waarschijnlijk wel ff lucht voor wat anders. Maar daarvoor zou je moeten weten hoe die scanning in elkaar zit (een scope of LA vertelt je dat direct).

Het probleem is niet zo zeer dat je zoveel naar buiten moet brullen, maar meer dat je erg snel moet reageren als 'jouw' trigger voorbij komt. Met software naar hardware luisteren is doorgaans een verloren wedstrijd op deze manier. Het gaat misschien (net) goed omdat die 'oud' (en dus relatief traag) is.

Dat was voor mij de reden om te zeggen: frut het in een EPROM (mag ook parellel flash of EEPROM zijn). Simpel. Goedkoop. Beetje glue-logic. Alleen de inhoud maken vereist ff een klein beetje software om op basis van het address te berekenen wat de ULA moet 'zien'. Maar dat is geen rocket science.

Nog een andere insteek: een stel serieel-parallel shift registers. Je schuift vanuit een Arduino ofzo de waarde erin. Dan doe je een LATCH. De outputEnable hang je aan een address lijn, de outputs aan de ULA. Je hebt er wel 8 nodig (waar je dan helaas slechts 5 bits van gebruikt...). En wellicht een beetje glue-logic omdat er wellicht iets geïnverteerd moet worden.

Interrupt gaat je inderdaad meer dan 4 cycles kosten. Als je iets met nauwkeurige timing wil doen moet je geen interrupts doen.

Dingen als Uart en bepalen welke kolom welke rij moet activeren moet je doen als je net een scan gehad hebt. Dus de truuk is kijken wanneer die scan komt.

Of gewoon besluiten dat je geen toetsaanslag simuleert als je met de UART bezig bent, dat kan ook. Nadeel is dat een toetsaanslag waarschijnlijk wel 100ms moet duren, en in die tijd kun je een hoop UART overflows missen.

Het kan inderdaad ook met een parallelle ((E)E)PROM. Maar de kant en klare arduino bordjes liggen wat meer voor het oprapen. TS moet maar beslissen waarmee hij het meest op zijn gemak is.

Arco

Special Member

Met een eprom (met de juiste inhoud ;) ) heel simpel:

Moeten wel pull-ups aan de KB2 pinnen

[Bericht gewijzigd door Arco op zondag 5 juni 2022 14:43:30 (22%)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
EricP

mét CE

Die pull-ups lijken al aanwezig te zijn (ze staan in het schema).
Verder zou ik een EPROM nemen met een input meer. Je hebt - als ik het goed heb - 39 toetsen en een shift. Voor 39 toetsen zit je op 6 bit. Allemaal ook nog een keer met een shift erbij maakt 7.
Maar inderdaad, dat idee dus...

Arco

Special Member

Klopt, was de shift vergeten... ;)

Die pull-ups zitten trouwens aan de (voor deze specifieke toepassing) verkeerde poort: aan KB1 i.p.v. KB2 (daar hebben de adreslijnen van de eprom weinig aan...)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
EricP

mét CE

Nee, ze zitten op beiden. In het schema van de spectrum ongeveer in het midden die op de address lijnen en links boven voor de 'data' lijnen. Of praten we nou langs elkaar heen??

Arco

Special Member

Op bovenstaande tekening ( https://www.1000bit.it/support/manuali/sinclair/zxspectrum/sm/topmem.g… ) zie ik geen pull-ups achter de diodes...

Met een processor als de 18F26Q10 is alles waarschijnlijk zelfs in 1 chip te proppen.
Die heeft CLC's. (Configurable Logic Cells, daar kun je hardwarematige gates en flipflops programmeren)
Kun je dan een standaard PS/2 toetsenbord op aansluiten.

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
EricP

mét CE

Die dioden heb je niet meer nodig... Op het schema lijken ze bij het keyboard te horen, aangezien ze niet op het schema van het 'mainboard' staan.
Maar goed... als de inderdaad op het 'mainboard' zitten, dan hebben pull-ups voordelen.

Als je inderdaad genoeg 'glue logic' met CLC manier kunt maken... 8 inputs, 5 outputs. In losse gates is dat wel ff een klusje (alhoewel het vooral copy-paste is als je de basis eenmaal hebt).

De RP2040 is een grappige processor: Er zitten een aantal PIO modules in. Die kan je programmeren om bepaalde dingen te doen op hoge snelheid en hoge nauwkeurigheid.

Als je dan toets 4-8 wil emuleren (kolom 4, rij 8), dan hang je zo'n PIO aan de kolom 4 input en rij 8 output en vertel je hem: Output volgt input! Dan reageert ie in een stuk of 8 ns. Opendrain ouput? Sure. Dat kan. En als je gesimuleerde keystroke weer voorbij is dan zet je de pio module gewoon uit. Andere toets? Gewoon in de config registers voor de PIO zetten dat ie een andere input pin/output pin combinatie heeft. Wil je twee toetsen tegelijk kunnen bedienen? Gewoon 2 PIO modules aanzetten (b.v. Shift-A).

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/

Dus het gaat om een ZX-Spectrum.

Die werkt met een minimum aan hardware en alles heeft meerdere functies. Dus ook de aansturing van het toetsenbord. De aansturende 8 adres lijnen zijn direct gekoppeld aan de adres bus van de processor en lopen dus op 3.5 MHz.

Dat wordt nog een uitdaging om dat met een micro te volgen.

Arco

Special Member

Met eerder genoemde eprom of CLC's zit de vertraging in de nS...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Het was toch zo als je een (rubber) toets van dat toetsenbordje indrukte dat het beeld wegviel omdat dan de CPU blokte op het loslaten van de toets? Omdat de CPU zelf ook de beeldopbouw deed.

1-st law of Henri: De wet van behoud van ellende. 2-nd law of Henri: Ellende komt nooit alleen.

Op 5 juni 2022 21:47:36 schreef henri62:
Het was toch zo als je een (rubber) toets van dat toetsenbordje indrukte dat het beeld wegviel omdat dan de CPU blokte op het loslaten van de toets? Omdat de CPU zelf ook de beeldopbouw deed.

Dat was de ZX80. De "truc" is, om op onderdelen te sparen, dat de processor meen ik ergens even wordt onderbroken door de ULA, de ULA geeft meen ik de clock aan de CPU, om andere communicatie te laten plaatsvinden.

Veel hangt af van hoe het keyboard uitgelezen wordt.
Als men eerst het adres selecteerd en een paar cycles later pas de lijn inklokt om te zien of er een toets is ingedrukt dan kan dat alles mee vallen.

De Teensy 4 die in andere topics wel voorbij komt loopt overigens default op 600 MHz, en heeft i/o tot 200 MHz. Geen idee hoe snel hij in deze toepassing is, maar het is een andere orde van grootte dan een 328.

Probeer het eerst simpel, en kijk pas verder als dat noodzakelijk blijkt. Als men de programmer en handigheid van programmeren heeft kan een EPROM natuurlijk ook simpel zijn, en zeker snel genoeg.
Maar dan had ik dit topic niet verwacht.

EricP

mét CE

Veel hangt af van hoe het keyboard uitgelezen wordt.
Als men eerst het adres selecteerd en een paar cycles later pas de lijn inklokt om te zien of er een toets is ingedrukt dan kan dat alles mee vallen.

Dat kun je gevoegelijk vergeten. Het heeft geen meerwaarde om de hele bus (!) meerdere cycles stil te gaan leggen om een toets uit te lezen. De meest voor de hand liggende is op de ene edge address setten en op de andere edge lezen.

De Teensy 4 die in andere topics wel voorbij komt loopt overigens default op 600 MHz, en heeft i/o tot 200 MHz. Geen idee hoe snel hij in deze toepassing is, maar het is een andere orde van grootte dan een 328.

Eens.

Probeer het eerst simpel, en kijk pas verder als dat noodzakelijk blijkt. Als men de programmer en handigheid van programmeren heeft kan een EPROM natuurlijk ook simpel zijn, en zeker snel genoeg.
Maar dan had ik dit topic niet verwacht.

Maar eigenlijk doet het wel min of meer wat TS wilde: single chip 40 schakelaars emuleren :) .

Ik vind die RP2040 die rew voorstelde wel een goeie. De PIO module van dat ding kan waarschijnlijk binnnen 1 klok reageren (en die interne klok is als ik me goed herrinner 133MHz, dus 7,5ns).

Bovendien heeft het iets moois een ZX spectrum een keyboard op basis van een dual-core,32 bit processor met 4x meer ram dan het hele adresbereik van de Spectrum te geven.

Of die PIO module makkelijker is dan een EEPROM betwijfel ik. Maar een PICO (RP2040 bordje) is makkelijker en goedkoper te krijgen (en te programmeren) dan een EEPROM.

(en die PICO heeft ongeveer dezelfde form-factor als een EEPROM!)

Arco

Special Member

Met een eprom heb je trouwens nog een extra input nodig: de ZX blijkt twee verschillende shifts te hebben. (CAPS SHIFT en SYMBOL SHIFT)
Wordt dus een 27C512...

Deze eprominhoud zou moeten werken...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com
EricP

mét CE

Je kunt het ook ranzig oplossen...
Met 38 toetsen en 2 shifts, heb je uiteindelijk 3x38 mogelijkheden (even aangenomen dat je niet beide shifts tegelijk gebruikt). Dat is bij mijn weten iets van 114. Dat past in 7 bits.

Arco

Special Member

Wat ik heb gelezen is dat je die shifts ook beide tegelijk moet kunnen gebruiken voor sommige functionaliteit...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Op 6 juni 2022 20:32:11 schreef Arco:
Met een eprom heb je trouwens nog een extra input nodig: de ZX blijkt twee verschillende shifts te hebben. (CAPS SHIFT en SYMBOL SHIFT)
Wordt dus een 27C512...

[bijlage]

Deze eprominhoud zou moeten werken...

Wow!