♬ ☘ Moja muzyka do kodowania ♬ ♬ ♬ ☘
♫ ♩ ♪ Collage ⚡ ☘ ⚡ Moonshine ♪ ♩ ♫
https://youtu.be/4huhmXEPujs
W ramach drobnych zmian w podejściu do grafomańskiej pisaniny postanowiłam oddzielić wątek o MB09 Monoboard od pobocznych tematów powstających ad-hoc, gdzie owa płytka pełni rolę platformy uruchomieniowej, a nie stanowi atrakcji sama w sobie. I tak oto pierwsza z `Nocnych przygód...` pisana na zasadzie – co by tu do tej Motorolki jeszcze podłączyć i zobaczyć jak działa. Oczywiście, jest to dalej (jak ktoś określił) sztuka dla sztuki, a dla mnie dodatkowo to nieustający trening klecenia w assemblerze procesora 6809 i kontynuacja rozpoczętej na jesieni przygody. To miłego czytania do poduszki.
Legginsy i Led-y
Wcześniejsze zakupy tak zwanych łachów na Aliexpress uważam za całkiem udane i potwierdzające matematyczną regułę że masa*jakość=const. Chińskie pstrokate legginsy na zajęciach pole-fit drę na potęgę, ale przy zamówionej sporej ilości problemu wielkiego z tym nie ma, no i zawsze mam nowe, w inny wzorek. A ostatnio, w ramach dalszego pogłębiania polsko–azjatyckich relacji handlowych i w trosce o zapewnienie koniunktury naszym rodzimym firmom kurierskim postanowiłam zakupić w Chinowie kilka elektronicznych klamotów.
Pierwszym z upatrzonych przydasiów jest moduł siedmiosegmentowych wyświetlaczy i przycisków opisywany w systemie (lang. PL) jako: "1 sztuk Klawisz Wyświetlacza Dla AVR Nowy Moduł 8-bitowy TM1638 8-bitowy Cyfrowy LED Tube" i nie ukrywam – już sam tytuł zrobił na mnie wrażenie. Cena za modułek również, ponieważ mój akurat egzemplarz kosztował deczko ponad pięć (słownie: 5) złotych.
A co on wart za tę niewielką kaskę – o tym dalej.
TM1638
Sercem płytki jest układ TM1638 firmy `Titan Micro Electronics` (no łał!) będący zintegrowanym sterownikiem wyświetlaczy siedmiosegmentowych wraz z funkcją obsługi klawiatury matrycowej.
To taki mały kombajn, z pomocą którego można w bardzo prosty sposób zrealizować podstawowy interfejs użytkownika, może atrakcyjnością nie wyrywający z majtek, ale całkiem funkcjonalny i co najważniejsze prosty do obsługi programowej. Dokumentacja firmowa w języku do złudzenia przypominającym angielski znajduje się na przykład tu:
https://www.openimpulse.com/blog/wp-con ... tm1638.pdf
Dla wielbicieli kwaśnych jabłuszek polecam wersję w oryginale, wydruk pozostawiony na stoliku to gwarant szacunku na dzielnicy czy też innym biurowym open-space.
http://www.titanmec.com/index.php/en/pr ... d/303.html
Tak ogólnie, to tych dokumentów jest w sieci kilka, na różnym poziomie estetyki, pomijając pocieszne konstrukcje językowe dokumencik zawiera wszelkie potrzebne sprawy merytoryczne i jest całkowicie wystarczający do napisania własnego oprogramowania, przerobiłam na sobie. Na marginesie, ja nie mogę oprzeć się wrażeniu, że koleżkowie mili, którzy popełnili kostkę TM1638 byli mocno zainspirowani układami firmy Maxim typu MAX6955, wyszła im równie sympatyczna konstrukcja. Otoczeniem kostki TM1638 jest garść guzików, ledów i dwa czteropozycyjne wyświetlacze, schemat zakupionej przeze mnie wersji jest luźną wariacją na temat typowej aplikacji układu i można go znaleźć na przykład na rysunku pod linkiem:
https://www.openimpulse.com/blog/wp-con ... ematic.jpg
Ktoś się zapewne jednak napracował aby stworzyć ten schemat, więc już bez zbędnej szydery pozwolę sobie zaprezentować swoją autorską wersję narysowaną wczoraj w Kicad:
Na rysunku mym pojawiają się także drobiazgi w postaci sygnalizacji zasilania oraz tabelka-help z adresami diodek oraz cyfr wyświetlacza.
Bit za bitem
Od strony programowej sprawa nie jest jakoś arcyskomplikowana, to klasyczne SPI aktywowane niskim poziomem sygnału /STB, dane są odbierane przez układ wraz z narastającym zboczem sygnału CLK. Sztuka cała to wysłanie odpowiednich komend do układu, wszelkie detale w data sheet. Do świeżo wyjętego z koperty modułu podeszłam z pewną nieufnością i aby w ogóle sprawdzić czy on działa zapięłam płytkę do Arduino z wgranym przykładem z sieci.
http://bienata.waw.pl/microgeek/TM1638/TM1638.ino
Przepraszam, ale nie pamiętam już skąd dokładnie ten plik pobrałam, zatem wrzucam swoją kopię. W sieci pełno jest takich demek, można sobie wybierać.
https://youtu.be/A3Tx8tcWf78
Modułek z Ardu na żywo całkiem ładnie mi zadziałał, nadesłana płytka okazała się w pełni sprawna, można zatem klecić swoje własne oprogramowanie sterujące.
Nauka chińskiego
Z lektury (ale jazda była) dokumentacji wyszło mi na to, że potrzebne będą procedurki zamykające podstawowe zagadnienia komunikacji z wyświetlaczem (póki co odczyt guzików pomijam, będzie potrzebne to się kiedyś dorobi). Są to kolejno: wysłanie ośmiu bitów danych w takt narastających zboczy generowanego sygnału CLK, wysłanie komendy sterującej, zapis do pamięci wyświetlacza pod zadany adres i wtenczas mamy kod jak niżej.
https://github.com/bienata/monoboard9/b ... 1638-1.asm
Procedurka tm1638_postbyte wysyła paczkę bitow przy niemym założeniu, że procedura ją wołająca ustawiła już /STB w stan L, czyli aktywowała transfer SPI, takoż ona zakończy transfer po zwróceniu sterowania przez tm1638_postbyte
tm1638-1.asm pisze:Kod: Zaznacz cały
; A - byte to send in raw form
tm1638_postbyte:
pshu a,b,x
ldx #8
sta temp ; save input
.loop:
; dt=0; ck=0, stb - bez zmian
anda #%0000.0001
beq .skipZero
;set data pin H
ldb #DAT_TM1638
stb PORT_TM1638
.skipZero:
; ck pulse
; __/--
ldb #CLK_TM1638
orb PORT_TM1638
stb PORT_TM1638
; --\__
ldb #0
stb PORT_TM1638
lda temp ; restore for a moment
lsra ; >> next incoming bit
sta temp ; save back
dex ; next byte
bne .loop
pulu a,b,x
rts
Procedurka tm1638_command to podstawa do wydawania poleceń kostce, włączania/wyłączania wyświetlacza, zmiany jasności (wypełnienie PWM) i trybu pracy zapis/odczyt. W tejże procedurze mamy rozpoczęcie i zakończenie jednobajtowego transferu SPI.
tm1638-1.asm pisze:Kod: Zaznacz cały
; A - command to execute
tm1638_command:
pshu a,b
ldb #0 ; strobe=0, dt=0, ck=0
stb PORT_TM1638
jsr tm1638_postbyte
ldb #STB_TM1638 ; strobe=1, dt=0, ck=0
stb PORT_TM1638
pulu a,b
rts
Procedurka tm1638_writeat to odrobinę bardziej skomplikowany potworek, rozpoczyna transfer SPI, poczym do kostki tm1638 wysyła wyliczony z danej wejściowej adres w pamięci wyświetlacza, następnie wysyła daną, którą kostka zapisze sobie pod wskazany adres. Specyfika aplikacji układu definiuje adresy pól odczytowych kolejno: 0xC0, 0xC2,.. 0xCE czyli co 2, parzyste. Dla garstki diodek LED luzem, zapiętych jako segmenty numer 9 kolejnych pól odczytowych adresy będą wynosiły odpowiednio 0xC1, 0xC3,…0xCF i takimi właśnie wartościami operuje bliźniacza procedurka tm1638_led. Po szczegóły odnośnie adresacji odsyłam do tabelki chart(2) na stronie 3 wskazanego datasheet, a poniżej procedurki do pisania po wyświetlaczu oraz zapalania wybranego LED-a. Pozycje cyfry/diodki określa wartość 0..7 podawana via rejestr B, kod siedmiosegmentowy budowany w sposób tradycyjny (bit 0 – segment a, bit 1 – b i tak dalej) podajemy jako parametr do rejestru A.
tm1638-1.asm pisze:Kod: Zaznacz cały
; A - 7-seg code to set
; B - display position (left 0..7 right)
tm1638_writeat:
pshu a,b,x
tfr d,x ; save a,b in x
lslb ; << 1
addb #$C0 ; digits
lda #0 ; strobe=0, dt=0, ck=0
sta PORT_TM1638
tfr b,a ; put add. in B and send
jsr tm1638_postbyte
tfr x,d ; restore input
jsr tm1638_postbyte
ldb #STB_TM1638 ; strobe=1, dt=0, ck=0
stb PORT_TM1638
pulu a,b,x
rts
tm1638-1.asm pisze:Kod: Zaznacz cały
; A - 1/0 to set
; B - LED position (left 0..7 right)
tm1638_led:
pshu a,b,x
tfr d,x ; save a,b in x
lslb ; << 1
addb #$C1 ; free leds
lda #0 ; strobe=0, dt=0, ck=0
sta PORT_TM1638
tfr b,a ; put add. in B and send
jsr tm1638_postbyte
tfr x,d ; restore input
jsr tm1638_postbyte
ldb #STB_TM1638 ; strobe=1, dt=0, ck=0
stb PORT_TM1638
pulu a,b,x
rts
Zerknijmy jeszcze na przebiegi czasowe złapane przy pomocy Analog Discovery 2 – widać wysłanie pojedynczej komendy (brightness) jak i dwubajtowy transfer polecenie+dana, to działanie writeat.
Cukierek też potrafi pokazać zdekodowane na żywca SPI, o proszę:
Nie zmienia to faktu, że poustawianie wszystkiego tymi jego gałeczkami może doprowadzić do rozstroju nerwowego, stanowoczo muszę to oskryptować w wolnej chwili.
Działanie przykładowej aplikacji pokazuje filmik:
https://youtu.be/gpRgG1qZ5JE
a jej pętlę główną fragment poniżej – dwa komplety cyferek na zmianę i biegający led plus zmiana jasności:
tm1638-1.asm pisze:Kod: Zaznacz cały
.here:
ldb #0
ldx #digits
.loop
lda ,x+
jsr tm1638_writeat
incb
cmpb #8
bne .loop
ldb #0
.loop1
lda #1
jsr tm1638_led
jsr delay
incb
cmpb #8
bne .loop1
ldb #7
.bright
tfr b,a
adda #$88
jsr tm1638_command
jsr delay
decb
bne .bright
ldb #0
.bright1
tfr b,a
adda #$88
jsr tm1638_command
jsr delay
incb
cmpb #8
bne .bright1
ldb #0
ldx #digits+8
.loop3
lda ,x+
jsr tm1638_writeat
incb
cmpb #8
bne .loop3
ldb #0
.loop2
lda #0
jsr tm1638_led
jsr delay
incb
cmpb #8
bne .loop2
jmp .here
digits: .db DIG_0,DIG_1,DIG_2,DIG_3
.db DIG_4,DIG_5,DIG_6,DIG_7
.db DIG_8,DIG_9,DIG_A,DIG_B
.db DIG_C,DIG_D,DIG_E,DIG_F
Kolejny film daje pojęcie o zmianach w poborze prądu przy różnych poziomach jasności wyświetlacza, widać zmiany w zakresie od praktycznie zera do 160mA.
https://youtu.be/XGOrtF-PhPU
Tu powstaje pytanie - dlaczego na filmiku występuje UM-4B a nie V640 lub UM-111? I dlaczego 160mA powyżej jest pogrubione? Przypadek? Nie sądzę...
Fragment kodu tak ładnie machający wskazówką amperomierza:
Kod: Zaznacz cały
.forever:
ldx #bright
.fade
lda ,x+
jsr tm1638_command
jsr delay
cmpx #brightEnd
bne .fade
jmp .forever
bright: .db $80
.db $88+0
.db $88+1
.db $88+2
.db $88+3
.db $88+4
.db $88+5
.db $88+6
.db $88+7
.db $88+6
.db $88+5
.db $88+4
.db $88+3
.db $88+2
.db $88+1
.db $88+0
.db $80
brightEnd:
Stos
Stos to świetna sprawa, aczkolwiek żywię uzasadnione obawy, że moje poprzedniczki sprzed kilkuset lat raczej nie podzielałyby tej opinii. Niemniej jednak w ochronie czy chwilowym przechowywaniu zmiennych podczas pracy programu stos jest narzędziem wręcz niezastąpionym. Równie łatwo może stać się narzędziem destrukcji generującym naprawdę trudne do identyfikacji anomalie w działaniu aplikacji, proszę zerknąć na filmik:
https://youtu.be/uyWvtKZlgKA
Programik testowy (wczesna, mocno rozwojowa wersja gdy walczyłam z kolejnymi procedurkami) jak widać działa sobie całkiem ładnie, ale tylko przez chwilę. Potem dzieje się coś dziwnego z wyświetlaczem, wizualnie zachowanie nie jest deterministyczne i prowadzi do tak zwanej zwiechy. Podejrzenia miałam różne – a może coś chińskie kabelki nie stykają? a może to domowa płytka-przelotka przy Motorolce nie kontaktuje? Toć tam fura drucików lutowanych przecież. No bo przecież niemożliwe jest abym to ja gdzieś dała ciała w programie! A tu proszę, sucharek ukryty siedział w procedurce tm1638_postbyte, czyli tej wywoływanej przy każdej atomowej operacji na wyświetlaczu. Polegał na niezbilansowanym stosie, inna ilość danych chomikowana rozkazem pshu a inna zdejmowana przez pulu, jakby klasyczny memory leak. Późniejszy eksperyment z wyświetlaniem wierzchołka stosu na terminalu wykazał, że owy systematycznie przesuwał się w kierunku dolnych adresów aż zawinąwszy się przez 0 wjechał w obszar ROM (wysokie adresu, od 0xE000) . Ponieważ Księżniczka Motorola ma na bogato 58kB pamięci RAM to taki rajd po kolejnych bankach pamięci trwał dłuższą chwilę, stąd złudne i mylne wrażenie, że aplikacja pada na wskutek czynników fizycznych.
Kod: Zaznacz cały
F000- 29 tm1638_postbyte:
F000- 30 ; b - byte 2 send
F000-8E 00 08 31 ( 3) ldx #8
F003- 32 .pb:
F003- 33 ; dt=0; ck=0, stb - bez zmian
F003-36 04 34 ( 6) pshu b ; save on stack
F005-C4 01 35 ( 2) andb #%0000.0001
F007-27 05 36 ( 3) beq .skipIfZero
F009- 37 ;set data pin H
F009-86 01 38 ( 2) lda #DAT_TM1638
F00B-B7 E0 01 39 ( 5) sta VIA1+ORA
F00E- 40 .skipIfZero:
F00E- 41 ; ck pulse
F00E- 42 ; __/--
F00E-86 02 43 ( 2) lda #CLK_TM1638
F010-BA E0 01 44 ( 5) ora VIA1+ORA
F013-B7 E0 01 45 ( 5) sta VIA1+ORA
F016- 46 ; --\__
F016-86 00 47 ( 2) lda #0
F018-B7 E0 01 48 ( 5) sta VIA1+ORA
F01B- 49
F01B-37 04 50 ( 6) pulu b ; restore for a moment
F01D-54 51 ( 2) lsrb ; >> next incoming bit
F01E-36 04 52 ( 6) pshu b ; save back
F020- 53
F020-30 1F 54 ( 5) dex
F022-26 DF 55 ( 3) bne .pb
F024- 56
F024-37 04 57 ( 6) pulu b ; just for stack balance
F026-39 58 ( 5) rts
Jak to mawiamy
program coraz bardziej
nie działa.
Okiem konsumentki
Jakieś wielkie rozwodzenie się nad tym czy warto to kupować czy nie jest chyba niecelowe. Jak ktoś może poczekać te trzy tygodnie to jak za piątak taki modułek jest całkiem fajnym urozmaiceniem zabaw z Ardu czy innymi platformami uC. Lokalnie też można nabyć tego typu płytki, cena jest jednak w okolicy kilkunastu złotych, za to dostępne są praktycznie od ręki, kwestia wyboru. Zwracam uwagę, że istnieje też wariant z większą klawiaturką oraz taki ze złączkami IDC10, do wyboru do koloru. Odnośnie jakości wykonania, narzekać raczej nie mogę.
No fakt, te wyświetlacze jakoś deczko krzywo ktoś wlutował, minimalnie ale jednak pod linijką widać.
Złączka do SPI też mogłaby być albo kątowa albo wrzucona jako luzem grzebyk 5-pin do samodzielnego wlutowania. W takiej konfiguracji nie da się modułku wmontować na front urządzenia, będzie problem właśnie o wysokość igiełek i skuwek z kabelkami, zostaje wtenczas albo wyciąć to zupełnie, albo przylutować się bezpośrednio do wyprowadzeń.
Płytka ma otworki montażowe M3, da się dorobić nóżki ze śrubek czy słupków dystansowych, moduł jest mały gabarytowo i całość nie wygina się przy naciskaniu guzików. Odnośnie dokumentacji modułku już pisałam, jest momentami przezabawna ale summa summarum na jej podstawie idzie tę płytkę w miarę szybko oswoić, czego wszystkim na koniec życzę.