13 ott 2020

STM8-BASIC: il più piccolo computer con interprete basic (3/4)

Nota: questo post fa parte di un articolo suddiviso in 4 sezioni:

  1. di 4 ☑
  2. di 4 ☑
  3. di 4 ☑
  4. di 4

 Allocare la nuova generazione

abbiamo visto nel precedente post la mappa di memoria in cui ospitare la generazione corrente delle nostre cellule.

Per ospitare la generazione successiva, utilizziamo gli 8 bytes immediatamente successivi della memoria.


Il programma

Vediamo quindi come passare dalla generazione corrente a quella futura:
dovremo fare una scansione di tutte le cellule della generazione corrente, per ogni cellula dovremo sapere se è viva o morta, e dovremo contare il numero di cellule vive intorno (chiamiamo questa somma S).
Con queste due informazioni stabiliremo lo stato della cellula nella prossima generazione:
  • cellula attualmente morta
    • se S=3, nella prossima generazione la cellula sarà viva
  • cellula attualmente viva:
    • se S=3 oppure S=2, nella prossima generazione la cellula sarà viva
  • in tutti gli altri casi, nella prossima generazione la cellula sarà morta.
Per implementare questo algoritmo dovremo effettuare una scansione dei byte della generazione corrente, per ogni byte effettuare una scansione dei bit (ovvero delle cellule) - calcolare lo stato del bit per la prossima generazione ed infine memorizzare lo stato della nuova generazione nell'area di memoria preposta.

La logica di massima del nostro programma BASIC sarà quindi:
  • (1) eseguiamo un ciclo sui byte della generazione corrente (dall'indirizzo $0201 a $0208) 
    • per ognuno di questi byte eseguiamo un ciclo sui bit (da 0 a 7) - chiamiamo R il byte corrente
      • per ogni bit, calcoliamo la somma delle cellule vive intorno ad esso
      • stabiliamo quindi se il corrispondente bit della prossima generazione sarà 1 o 0 (cellula viva o meno)
    • al termine del ciclo sui bit avremo calcolato un intero byte della prossima generazione, chiamiamo T questo byte
    • salviamo il byte T in un indirizzo 9 locazioni più avanti rispetto al corrispondente byte R (es: da $0203 a $0203+9 = $020C)
  • al termine del ciclo sui byte, avremo le locazioni $020A-$0211 riempite con la nuova generazione
  • (2) copiamo la nuova generazione dalle locazioni [$020A-$0211] alle locazioni [$0201-$0208]
  • (3) copiamo il primo byte della nuova generazione da $020A a $0209
  • (4) copiamo l'ultimo byte della nuova generazione da $0211 a $0200
  • ricominciamo da capo.
Ho evidenziato in colore blu le operazioni eseguite per ogni byte della generazione corrente, ed in colore rosso le operazioni eseguite per ogni bit del byte corrente.

Per ogni byte preso in esame (ricordo che per calcolare la somma delle cellule vive dovrò tenere conto anche del byte precedente e del byte successivo) nella generazione corrente il programma calcolerà il corrispondente byte della generazione futura e lo salverà nell'opportuno indirizzo (9 locazioni più "in basso" nella mappa della memoria).


Dalle idee al codice

Proviamo ora a strutturare un programma BASIC su questa logica; in questa prima stesura trascuriamo i dettagli del calcolo della cellula per la nuova generazione (righe tra la 90 e la 140) .

10 REM (1) CICLO SUI BYTE IN RAM
20 FOR A=$0201 TO A+7
30 REM INIZIALIZZO BYTE T DELLA PROSSIMA GENERAZIONE
40 T=0 
50 REM CARICO IL BYTE R DELLA GENERAZIONE CORRENTE
60 R=PEEK A
70 REM CICLO SUI BIT DEL BYTE R
80 FOR N=0 TO 7

90 REM CALCOLO IL VALORE DELLA CELLA
100 REM CORRISPONDENTE AL BIT 2^N DEL BYTE T
... 
140 REM FINE CALCOLO
150 NEXT N
160 REM C = INDIRIZZO IN CUI DEVO SCRIVERE
170 REM IL BYTE DELLA PROSSIMA GENERAZIONE
180 C=A+9
190 POKE C,T

200 NEXT A
210 REM (2) COPIO LA NUOVA GENERAZIONE CALCOLATA
220 REM DA $020A-$0211 A $0201-$0208
230 FOR B=$0201 TO B+7
240 P=PEEK B+9
250 POKE B,P
260 NEXT B
270 REM (3) COPIO IL BYTE IN $020A SU $0209
280 P=PEEK $020A
290 POKE $0209,P
300 REM (4) COPIO IL BYTE IN $0211 SU $0200
310 P=PEEK $0211
320 POKE $0200,P
330 SLEEP 1
340 GOTO 10

Questa è la struttura generale del programma, naturalmente mancano ancora le parti per:
  • stampare a video la generazione corrente
  • calcolare il byte T della generazione futura, che si traduce praticamente in
    • calcolare la somma delle cellule vive intorno al bit n-esimo del byte corrente
Per ora è tutto, vedremo nell'ultimo post come effettuare il calcolo del byte della nuova generazione, e vedremo se riusciremo a fare stare il nostro programma nei 630 byte a disposizione.

Nessun commento:

Posta un commento