Mix
Random mix of pages and files
Blog 2025
2025.02.25 18:35:04 - 2025.02.25 18:35:08 end blog Gilhad

2025.03.28

Na Arduinu generuju kompozitní signál pro monitor a čtu PS/2 klávesnici. Generování kompozitního signálu znamená každých 16 taktů poslat na výstup další byte. Základní čtení PS/2 dat se mi podařilo rozložit na části, které během generování jednoho řádku zkontrolují PS/2 3x. Ale mimo generování řádků (při horizontálních a vertikálních pulzech) stihnou hodiny PS/2 projít několik tiků, takže je potřeba PS/2 sledovat i v té době. Zároveň je to jediná doba, kdy může běžet hlavní program, takže ji nemůžu celou zabrat busy-wait cykly. Tak jsem zvolil pověsit interrupt na změnu pinu A0 (kde jsou hodiny PS/2) a sledovat změnu jen při změně hodin. Ale zjistil jsem, že se mi takřka pro každý scan kód (11 pulsů PS/2) zavolá při každém z těch 11 pulzů. Což asi není dobře, protože většina pulsů by měla spadnout do oblasti řádků a tady být ošetřena tam. Tyto interrupty na začátku každého řádku zakazuju a na konci každého řádku povoluju, ale mažu pending příznak. Níže je příslušný kus kódu. Zdá se, že to nefunguje tak, jak bych předpokládal - mám chybu v úvahách, nebo v provedení?

Zakázání
PCMSK1 &= ~(1 << PCINT8);  // Disable interrupt for A0

Povolení
PCIFR  |= bit (PCIF1);   // clear any outstanding interrupts
PCMSK1 |= (1 << PCINT8);   // Enable interrupt for A0

Počáteční nastavení
PCMSK1 |= (1 << PCINT8); // Enable PCINT8 (A0 is PC0)
PCIFR  |= (1 << PCIF1);   // clear any outstanding interrupts
PCICR  |= (1 << PCIE1);   // Enable Pin Change Interrupt for PCINT[14:8] (Port C)

Nakonec se na osciloskopu ukázalo, že vlastně všechno funguje správně, ale těch 11 pulzů u PS/2 je 22 hran a z nich asi tak 2/3 spadly do řádku a 1/3 - tedy 7 mimo a byla správně zachycena interruptem. V reálném čase ta čísla byla nepřesná a trochu matoucí. A chyby ve výstupu na monitor byly způsobené tím, že jak zobrazování, tak PS/2 mimo řádky jdou přez interrupty a pokud se ty interrupty nešikovně sešly, tak se o kus odsunuly a řádek byl nakreslen špatně. Takže to bude chtít řešit jinak. Ale možná půjde zakázat PS/2 interrupt už při sync pulzu, pokud následuje řádek, a takto vzniklá mezera už nedovolí propadnutí pulzu, ale zabrání kolizi interruptů. A čtení bufferu bude muset být pořešeno s ohledem na interrupty nějak zabezpečeně, nebo naopak vtipně. (Čtení mění ocas, zápis hlavu, ale v systému je jen jedno čtení a jeden zápis bez ohledu na interrupty.)

2025.03.27 Matrix a databáze lines

Trochu jsem to dočesal, přidal operátor << a převedl to na něj, přidal Matrix jako screensaver a přidal jednoduché rejdění šipkama a vypadá to docela dobře. Do loga jsem přidal aktuální volnou RAM a FLASH, bude to ještě chtít dořešit čmouhy při psaní (a ujistit se, že to chodí i na RCA) - pro debug můžu třeba místo LEDek měnit znaky na obrazovce, dlouhodobě se to vždycky ukáže, takže můžu přejít na styl vyšších počítačů :)

Rozchodil jsem jednoduchou databázi pro ukládání dat lines, kterou plánuju už kdoví jak dlouho, pomocí flask to bylo překvapivě snadné - jednoduchá webovka je hotová raz-dva a dá se používat, složitosti později, časem.

from flask import Flask, request, render_template, redirect, url_for
import pymysql

app = Flask(__name__)

# Připojení k databázi
def get_db_connection():
        return pymysql.connect(
                host='localhost',
                user='gilhad',
                password='gilhad',
                database='grafana'
        )
@app.route('/<path:path>')
def static_file(path):
        return app.send_static_file(path)

@app.route('/', methods=['GET'])
def index():
                return render_template('index.html')

@app.route('/vahy', methods=['GET', 'POST'])    # {{{
def vahy():
        if request.method == 'POST':
                value = request.form['value']
                if value:
                        conn = get_db_connection()
                        cursor = conn.cursor()
                        cursor.execute('INSERT INTO vahy (value) VALUES (%s)', (value,))
                        conn.commit()
                        cursor.close()
                        conn.close()
        # Při GET nebo po odeslání nové hodnoty zobrazení posledních 5 hodnot
        conn = get_db_connection()
        cursor = conn.cursor(pymysql.cursors.DictCursor)
        cursor.execute('SELECT value, timestamp FROM vahy ORDER BY timestamp DESC LIMIT 5')
        last_values = cursor.fetchall()
        cursor.close()
        conn.close()
        return render_template('value.html', values=last_values, Title="vahy")          # }}}
# ....

if __name__ == '__main__':
        app.run(debug=True)

templates/value.html:

<!DOCTYPE html>
<html lang="en">
<head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>{{Title}}</title>
        <link rel="stylesheet" href="./css/css.css">
        <link rel="icon" href="./favicon.ico">
</head>
<body>
        <a href="/">index</a><br>
        <H1>{{Title}}</H1>
        <table>
                <tr><td class="right">
                        <form method="POST">
                                <button type="submit">Odeslat</button></td><td class="right">
                                <label for="value">Value:</label> <input type="float" id="value" name="value" required>
                        </form></td>
                </tr>
{% for entry in values %}
                <tr><td class="right">{{ entry.timestamp }} </td><td class="bold right"> {{ entry.value }} </td></tr>
{% endfor %}
        </table>
</body>
</html>

static/css/css.css

static/favicon.ico

a hotovo jedem :)

2025.03.22 Arduino Day

Byl jsem na Arduino dni a bylo to príma. Včera jsme tam tahali stoly, přez noc jsem konečně rozchodil PS2-RCA-VGA pro Nano na breadboardu (minimálně po HW stránce, SW ještě potřebuje dost práce) a dnes jsem se tím mohl chlubit :)

Vypadá to teď nějak takhle - breadboard-008-PS2-RCA-VGA-Nano.pdf - to schéma je určeno pro úpravy breadboardu, proto je spíš ve tvaru, jak to tam leží. Napájení jsem moc nekreslil.

breadboard-008-PS2-RCA-VGA-Nano.png

Důležité úpravy proti původnímu projektu jsou, že dodržuju výstupní úrovně 0 - 0.3 - 1.0 V a okolo synchronizačních pulzů to není vyvýšené, jak to bylo předtím, kdy tam byl připojený neaktivní pin, takže teď není problém co je synchronizační pulz a co je hodně černá černá. Takže výstup v Tx má HW pulldown asi 1.3 kΩ (ono je to celkem jedno kolik přesně) a jde ještě do AND hradla, které to znormalizuje na buď 0, nebo 5V. Druhý vstup do AND je suppress pin, který je pořád jako OUTPUT a buď má 1 (volno), nebo 0 (suppress). Za AND (NAND+NOT = půlka 7400) pak je čistý výsledek. Ten přez odpor 440 Ω a 1 kΩ pullup tvoří dělič pro 75 Ω monitor a logická nula vyjde na 0.3V, zatímco logická jednička na 1.0V. A tranzistor S8050 to uzemní pro synchronizažní pulzy na čistých 0V. (A díky 440 Ω jde tranzistorem, i hradlem maximálně nějakých 12mA). Časem se asi ještě podívám na délky těch pulzů, ale to už je SW problém.

Během dne jsem ještě na to zkonvertoval Blocks (tetris) a nějak to chodí (jako technologické demo, do rozumného použití tomu chybí ještě dost - demo-breadboard-008-PS2-RCA-VGA-Nano.tar.gz) - F12 přepíná režim, F1 a F2 vypisují různými způsoby 0..255 na obrazovku, F3 popíše celou obrazovku jedním znakem a pak dalším a dalším, F4 je tetris a Esc popíše obrazovku znakem stiskuntým před tím Esc.

Na composite video ještě nějak "drhnou" scankódy - musím zkontrolovat, zda se správně zapíná přerušení mimo kreslení řádek. A trochu učesat tu rutinu, aby nebyly problémy s autorepeatem a delšími scankódy. A aby se nepřepínalo dvakrát. A aby Esc nepožral další klávesu. A aby šel přepínat režim i během tetrisu. A třeba i z tetrisu nějak vyskočit. A tak podobně - no, je to jen první nástřel :)

2025.03.20 Arduino composite upřesnění

  • Umělák tvrdí něco jako, že:
  • Typický kompozitní videosignál má špičkovou hodnotu 1 V (od špičky k špičce) při impedanci 75 Ω.
  • To zahrnuje synchronizační pulzy, které obvykle dosahují úrovně 0 V, černá úroveň je 0.3V, zatímco maximální úroveň bílé je 0,7 V nad černou úrovní tedy 1V. Synchronizační pulzy jsou nezbytné pro správné zobrazení obrazu, protože určují začátek každého řádku a snímku.
  • Pro evropský standard PAL je horizontální frekvence 15 625 Hz (64 µs na řádek) a vertikální frekvence 50 Hz. Každý řádek začíná horizontálním synchronizačním pulzem trvajícím přibližně 4,7 µs, po kterém následuje tzv. "back porch" (časový úsek před začátkem viditelné části řádku) o délce zhruba 5,7 µs, a poté samotná viditelná část signálu.
  • https://www.youtube.com/watch?v=xeh48wK4TOw
  • Tady zase tvrdí, že řádek horizontálním pulzem končí hned po datech
  NTSC PAL
Field duration 1/60 sec 1/50 sec
Vertical blanking 1333 us 1600 us
Line loss due to vertical blanking 21 lines 25 lines
Line duration 63.5 us 64 us
Horizontal blanking 10.2 us 10.25 us
Visible trace time 53.3 us 53.75 us
  • A tady je detailně popsané časování - asi zatím nejlepší, na co jsem narazil.
  • Moje shrnutí zatím
    • sync pulzy jdou na nulu, jinak to má být mezi 0.3V a 1.0V
    • krátká černá před sync pulzem, i za ním - viz timing obrázky
    • 75 Ω na monitoru
      • při černé = 0.3V tím teče 0.3 / 75 = 4 mA
      • při bílé = 1V tím teče 1 / 75 = 13.3 mA
      • 5V / 13.3mA = 375 Ω - 300 Ω od pinu + 75 Ω do monitoru
      • použiju uměláka a ošklivý brute force a vyjde mi dělič takový: R1=75 Ω, R2 = 430 Ω, R3 = 992.31 Ω, Voltage on divider = 0.30 V a 1.0V - odhadem proč ne, zapojíme vyzkoušíme
        • 220/3=73 Ω, 1 kΩ a 440 Ω dá podobnou děličku, 0.3V a 0.9V je ok v rámci improvizace a přesnosti měření.
        • pro sync použiju mosfet na nulu a ono to snad nějak něco

2025.03.02 Arduino + PS/2 + VGA + RCA composite video

Rozchodil jsem Arduino + PS/2 + VGA + RCA composite video, teda zatím kompozit a VGA zvlášť, naráz to nepoběží, není dost výkonu, ale chtěl bych to časem umět i přepínat. Jak při startu, tak i za chodu. viz HW/PS2-RCA-VGA. Asi to taky sjednotím na VGA rozměr 40x25 (RCA umí asi 46x29, ale správně s PS/2 pracuje pro 43x29 a míň, jinak to při použití klávesnice skáče) a použiju ten jeho os::něco přístup. Budu si taky chtít upravit znaky, nevyhovují mi tak úplně ani na jednom. A asi bych to měl rád jako normálně kompilované, tedy přez něco jako Sudar Makefile raději než přez arduino-cli s jejich přístupem ke knihovnám a podobně. Udělal jsem si taky repozitář MakeArduino a chtěl bych to tam nějak rozběhat.

A upravil jsem si fonty v Gimpu - 2048x8(nebo 9) bitů obrázky, vodorovně zazrcadlené (protože je shiftuju ven počínaje LSB) a vyexportované jako *.bmx jsou přesně to C pole, které potřebuju .. }}}

2025.02.25 Nový rok