Il prossimo 29 agosto Dropbox terminera' il supporto per il client Windows XP.
Al contrario di come fanno altre ditte, per esempio Google con Chrome, la fine del supporto non indica che non saranno piu' sviluppati aggiornamenti ma che il client terminera' il suo funzionamento (sara' sempre disponibile l'interfaccia web)
Considerando che Dropbox e' di proprieta' Microsoft e che il servizio e' fondamentalmente gratuito non e' da biasimare Microsoft se cerca di piazzare qualche SO nuovo...ma forse una soluzione semplice esiste ed e' quella di usare un client Python usanto le API dell'SDK di Dropbox
Per usare il client Python ci si deve prima registrare su Dropbox Developer, creare una App (la piu' semplice e' App Folder) e generare un Access Token
Successivamente si scaricare l'SDK Python di Dropbox da questo indirizzo https://github.com/dropbox/dropbox-sdk-python installandolo poi con il classico
python setup.py install
a questo si puo' modificare il programma updown.py che permette di sincronizzare una cartella (cosi' come fa il client). Per personalizzare la directory da sincronizzare si deve modificare la rootdir (di default e' Downloads) e la cartella remota di Dropbox.
il progrramma si lancia quindi con la sintassi (il token si deve copiare dalle impostazioni della app)
python updown.py --token xxxxxxxxxxxxxxxxxxxxxxxxxxxxx --yes
(lo yes finale risponde in modo affermativo alle domande in modo da sovrascrivere in modo automatico)
i file sincronizzati non si trovano nella radice di Dropbox ma nella sottodirectory /App/nomedellaApp
mercoledì 8 giugno 2016
Mandelbrot su C64 in Assembler
Frugando su internet ho trovato la versione in Assembler di Mandelbrot per C64 compresa nel progetto Resurrection (sotto cartella Mandelbrot)
Il codice e' ben commentato ed il risultato e' in modalita' testo
Il tempo di calcolo su VICE in emulazione del tempo reale del C64 risulta essere di 90 secondi con 26 iterazioni per punto
Il codice e' compilabile con il crosscompiler ACME e necessita della libreria stdlib
----------------------------------------------------------------
;Mandelbrot test code
!source "../stdlib/stdlib.a"
!to "Mandelbrot.prg", cbm
!sal
!sl "Mandelbrot.map"
!svl "Mandelbrot.lbl"
!cpu 6510
!ct pet
!source "../stdlib/BASICEntry80d.a"
!macro OutputFAC {
jsr $bddd ; Convert FAC#1 to ASCII String. Kills FAC#2
jsr $b487 ; Set Up String
jsr $ab21 ; Output String
}
LDFAC = $bba2
STFAC = $bbd4
SUBFAC = $b850
DIVFAC = $bb0f
CMPFAC = $bc5b
MULFAC = $ba28
ADDFAC = $b867
SETFAC = $b391
!macro LoadFAC .addr {
lda #<.addr
ldy #>.addr
jsr LDFAC
}
!macro StoreFAC .addr {
ldx #<.addr
ldy #>.addr
jsr STFAC
}
!macro SubMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr SUBFAC
}
!macro SubFACMem .addr {
+StoreFAC Temp
+LoadFAC .addr
+SubMemFAC Temp
}
!macro DivMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr DIVFAC
}
!macro DivFACMem .addr {
+StoreFAC Temp
+LoadFAC .addr
+DivMemFAC Temp
}
!macro CmpFACMem .addr {
+StoreFAC Temp
+LoadFAC .addr
+CmpMemFAC Temp
}
!macro CmpMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr CMPFAC
}
!macro MulMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr MULFAC
}
!macro AddMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr ADDFAC
}
!macro SetFAC_Y {
lda #0
jsr SETFAC
}
kMaxIterations = 26
!zn
*=BASICEntry
cld
jsr CINT
; Speed testing for some FP ops. As we can see even some simple operations are very slow
!if 0 {
sei
.tl1
lda #0
sta VIC2BorderColour
+MACROWaitForRaster 64
inc VIC2BorderColour
+LoadFAC xmin
inc VIC2BorderColour
+SubMemFAC xmax
inc VIC2BorderColour
+DivFACMem ScrW
inc VIC2BorderColour
+StoreFAC xs
inc VIC2BorderColour
+MulMemFAC xs
inc VIC2BorderColour
+StoreFAC xs
inc VIC2BorderColour
jmp .tl1
}
; The main Mandelbrot code.
;xs=(xmax-xmin)/40.0;
+LoadFAC xmin
+SubMemFAC xmax
+DivFACMem ScrW
+StoreFAC xs
;ys=(ymax-ymin)/24.0;
+LoadFAC ymin
+SubMemFAC ymax
+DivFACMem ScrH
+StoreFAC ys
;for (y=0;y<24;y++) {
lda #0
sta y
.l1
; for (x=0;x<40;x++) {
lda #0
sta x
.l2
; p=xmin+(x*xs);
ldy x
+SetFAC_Y
+MulMemFAC xs
+AddMemFAC xmin
+StoreFAC p
; q=ymin+(y*ys);
ldy y
+SetFAC_Y
+MulMemFAC ys
+AddMemFAC ymin
+StoreFAC q
; xtemp=0;
; x0=0;
; y0=0;
ldy #0
+SetFAC_Y
+StoreFAC x0
+StoreFAC y0
; i=0;
lda #0
sta i
.while
; while (((x0*x0)+(y0*y0))<4 && ++i<kMaxIterations) {
; i check, first, simple integer check
lda i
cmp #kMaxIterations
bcc .ltkMaxIterations
jmp .escape
.ltkMaxIterations
; mul check
+LoadFAC x0
+MulMemFAC x0
+StoreFAC Temp2
+LoadFAC y0
+MulMemFAC y0
+AddMemFAC Temp2
+CmpFACMem Escape
bcc .lt4
jmp .escape
.lt4
;++i
inc i
; xtemp = (x0*x0) - (y0*y0) + p
+LoadFAC x0
+MulMemFAC x0
+StoreFAC Temp2
+LoadFAC y0
+MulMemFAC y0
+SubMemFAC Temp2
+AddMemFAC p
+StoreFAC xtemp
; y0=(2 * x0 * y0) +q;
+LoadFAC x0
+MulMemFAC y0
+StoreFAC Temp2
ldy #2
+SetFAC_Y
+MulMemFAC Temp2
+AddMemFAC q
+StoreFAC y0
; x0=xtemp;
+LoadFAC xtemp
+StoreFAC x0
; }
jmp .while
.escape
; Range check to adjust for printable characters
lda i
; lsr ; Potential for shit adjustment, change kMaxIterations to accomodate
cmp #26 ; Letters in the alphabet!
bcc .okChar
lda #' '
jmp .rawOut
.okChar
clc
adc #64
.rawOut
jsr CHROUT
; Finish for loops
inc x
lda x
cmp #40
beq .ol2
jmp .l2
.ol2
inc y
lda y
cmp #24 ; MPi: TOOD: Keep the last line clear for an IRQ scrolling message
beq .ol1
jmp .l1
.ol1
.flash
; inc VIC2BorderColour
jmp .flash
; C64 Floating point values
; MPi: TODO: Must update the assembler to create these
xmin !by $82, $a0, $00, $00, $00 ; -2.5
xmax !by $81, $40, $00, $00, $00 ; 1.5
ymin !by $81, $c0, $00, $00, $00 ; -1.5
ymax !by $81, $40, $00, $00, $00 ; 1.5
ScrW !by $86, $20, $00, $00, $00 ; 40
ScrH !by $85, $40, $00, $00, $00 ; 24
Escape !by $83, $00, $00, $00, $00 ; 4
; Float storage
Temp = *
Temp2 = * + 5
xs = * + 10
ys = * + 15
p = * + 20
q = * + 25
xtemp = * + 30
x0 = * + 35
y0 = * + 40
; Bytes
x = * + 45
y = * + 46
i = * + 47
Il codice e' ben commentato ed il risultato e' in modalita' testo
Il tempo di calcolo su VICE in emulazione del tempo reale del C64 risulta essere di 90 secondi con 26 iterazioni per punto
Il codice e' compilabile con il crosscompiler ACME e necessita della libreria stdlib
----------------------------------------------------------------
;Mandelbrot test code
!source "../stdlib/stdlib.a"
!to "Mandelbrot.prg", cbm
!sal
!sl "Mandelbrot.map"
!svl "Mandelbrot.lbl"
!cpu 6510
!ct pet
!source "../stdlib/BASICEntry80d.a"
!macro OutputFAC {
jsr $bddd ; Convert FAC#1 to ASCII String. Kills FAC#2
jsr $b487 ; Set Up String
jsr $ab21 ; Output String
}
LDFAC = $bba2
STFAC = $bbd4
SUBFAC = $b850
DIVFAC = $bb0f
CMPFAC = $bc5b
MULFAC = $ba28
ADDFAC = $b867
SETFAC = $b391
!macro LoadFAC .addr {
lda #<.addr
ldy #>.addr
jsr LDFAC
}
!macro StoreFAC .addr {
ldx #<.addr
ldy #>.addr
jsr STFAC
}
!macro SubMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr SUBFAC
}
!macro SubFACMem .addr {
+StoreFAC Temp
+LoadFAC .addr
+SubMemFAC Temp
}
!macro DivMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr DIVFAC
}
!macro DivFACMem .addr {
+StoreFAC Temp
+LoadFAC .addr
+DivMemFAC Temp
}
!macro CmpFACMem .addr {
+StoreFAC Temp
+LoadFAC .addr
+CmpMemFAC Temp
}
!macro CmpMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr CMPFAC
}
!macro MulMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr MULFAC
}
!macro AddMemFAC .addr {
lda #<.addr
ldy #>.addr
jsr ADDFAC
}
!macro SetFAC_Y {
lda #0
jsr SETFAC
}
kMaxIterations = 26
!zn
*=BASICEntry
cld
jsr CINT
; Speed testing for some FP ops. As we can see even some simple operations are very slow
!if 0 {
sei
.tl1
lda #0
sta VIC2BorderColour
+MACROWaitForRaster 64
inc VIC2BorderColour
+LoadFAC xmin
inc VIC2BorderColour
+SubMemFAC xmax
inc VIC2BorderColour
+DivFACMem ScrW
inc VIC2BorderColour
+StoreFAC xs
inc VIC2BorderColour
+MulMemFAC xs
inc VIC2BorderColour
+StoreFAC xs
inc VIC2BorderColour
jmp .tl1
}
; The main Mandelbrot code.
;xs=(xmax-xmin)/40.0;
+LoadFAC xmin
+SubMemFAC xmax
+DivFACMem ScrW
+StoreFAC xs
;ys=(ymax-ymin)/24.0;
+LoadFAC ymin
+SubMemFAC ymax
+DivFACMem ScrH
+StoreFAC ys
;for (y=0;y<24;y++) {
lda #0
sta y
.l1
; for (x=0;x<40;x++) {
lda #0
sta x
.l2
; p=xmin+(x*xs);
ldy x
+SetFAC_Y
+MulMemFAC xs
+AddMemFAC xmin
+StoreFAC p
; q=ymin+(y*ys);
ldy y
+SetFAC_Y
+MulMemFAC ys
+AddMemFAC ymin
+StoreFAC q
; xtemp=0;
; x0=0;
; y0=0;
ldy #0
+SetFAC_Y
+StoreFAC x0
+StoreFAC y0
; i=0;
lda #0
sta i
.while
; while (((x0*x0)+(y0*y0))<4 && ++i<kMaxIterations) {
; i check, first, simple integer check
lda i
cmp #kMaxIterations
bcc .ltkMaxIterations
jmp .escape
.ltkMaxIterations
; mul check
+LoadFAC x0
+MulMemFAC x0
+StoreFAC Temp2
+LoadFAC y0
+MulMemFAC y0
+AddMemFAC Temp2
+CmpFACMem Escape
bcc .lt4
jmp .escape
.lt4
;++i
inc i
; xtemp = (x0*x0) - (y0*y0) + p
+LoadFAC x0
+MulMemFAC x0
+StoreFAC Temp2
+LoadFAC y0
+MulMemFAC y0
+SubMemFAC Temp2
+AddMemFAC p
+StoreFAC xtemp
; y0=(2 * x0 * y0) +q;
+LoadFAC x0
+MulMemFAC y0
+StoreFAC Temp2
ldy #2
+SetFAC_Y
+MulMemFAC Temp2
+AddMemFAC q
+StoreFAC y0
; x0=xtemp;
+LoadFAC xtemp
+StoreFAC x0
; }
jmp .while
.escape
; Range check to adjust for printable characters
lda i
; lsr ; Potential for shit adjustment, change kMaxIterations to accomodate
cmp #26 ; Letters in the alphabet!
bcc .okChar
lda #' '
jmp .rawOut
.okChar
clc
adc #64
.rawOut
jsr CHROUT
; Finish for loops
inc x
lda x
cmp #40
beq .ol2
jmp .l2
.ol2
inc y
lda y
cmp #24 ; MPi: TOOD: Keep the last line clear for an IRQ scrolling message
beq .ol1
jmp .l1
.ol1
.flash
; inc VIC2BorderColour
jmp .flash
; C64 Floating point values
; MPi: TODO: Must update the assembler to create these
xmin !by $82, $a0, $00, $00, $00 ; -2.5
xmax !by $81, $40, $00, $00, $00 ; 1.5
ymin !by $81, $c0, $00, $00, $00 ; -1.5
ymax !by $81, $40, $00, $00, $00 ; 1.5
ScrW !by $86, $20, $00, $00, $00 ; 40
ScrH !by $85, $40, $00, $00, $00 ; 24
Escape !by $83, $00, $00, $00, $00 ; 4
; Float storage
Temp = *
Temp2 = * + 5
xs = * + 10
ys = * + 15
p = * + 20
q = * + 25
xtemp = * + 30
x0 = * + 35
y0 = * + 40
; Bytes
x = * + 45
y = * + 46
i = * + 47
----------------------------------------------------------------
IEEE 754
Si tratta di un metodo di memorizzazione di numeri float con varia lunghezza nel numero di bit (in questo caso sara' utilizzata solo la rappresentazione a 32 bit). Un convertitore on line di numeri in formato IEEE754 puo' esssere trovato a questo link
I bit sono cosi' divisi
1 bit di segno
8 bit di esponente : 2 elevato all'esponente
23 bit : mantissa del numero
In questo formato i numeri 12.5 e 3.5 ottengono la seguente rappresentazione binaria
12.5 0 10000010 10010000000000000000000 1.5625 4718592
per moltiplicare i due numeri (12.5*3.5=43.75) si procede sommando gli esponenti e moltiplicando le mantisse. In questo caso 2^(1+3)*(1.5625*1.75)=2.734375*2^4. La mantissa deve essere normalizzata perche' e' superiore a 2 per cui il risultato sara' 1.3671875*2^5 ovvero 43.75
I bit sono cosi' divisi
1 bit di segno
8 bit di esponente : 2 elevato all'esponente
23 bit : mantissa del numero
In questo formato i numeri 12.5 e 3.5 ottengono la seguente rappresentazione binaria
12.5 0 10000010 10010000000000000000000 1.5625 4718592
3.5 0 10000000 11000000000000000000000 1.75 6291456
il primo bit e' in entrambi i casi 0 perche' i due numeri sono positivi
12.5 puo' essere espresso come 2^3 *1.5625. L'esponente e' quindi 3 ma deve essere sommato il valore di 127 per cui l'esponente e' 127 + 3 = 130d = 10000010b. Infine 10010000000000000000000 e' la rappresentazione binaria di 1.5625
Lo stesso si puo' ripetere per il numero 3.5 che puo' essere espresso come 2^1*1.75
Per sommare i due numeri si procede allineando gli esponenti a quello piu' basso (in questo caso 1). 12.5 viene quindi espresso come 6.25*2^1 (spostando l'esponente di due si moltiplica la mantissa per quattro ovvero 2^spostamento). A questo punto si sommando le mantissa e la somma e' uguale a (6.25+1.75)*2^1 = 8*2=16 ovvero il risultato desiderato (12.5+3.5)
per moltiplicare i due numeri (12.5*3.5=43.75) si procede sommando gli esponenti e moltiplicando le mantisse. In questo caso 2^(1+3)*(1.5625*1.75)=2.734375*2^4. La mantissa deve essere normalizzata perche' e' superiore a 2 per cui il risultato sara' 1.3671875*2^5 ovvero 43.75
Perche' tanto confusione .. perche' ai computer piacciono i numeri a base due ed interi
Questa e' un sistema standardizzato ma esistono altri modi per descrivere un numero. In questo fantastico documento del 1976 a firma tale Roy Rankin e Steve Wozniak sulle procedure matematiche per il 6502 con una rappresentazione a 32 bit nel formato
Exponent Two's Complement Mantissa SEEEEEEE SM.MMMMMM MMMMMMMM MMMMMMMM n n+1 n+2 n+3
Repository per Yocto su Intel Edison
Come fatto notare in un precedente post, il repository di default opkg di Intel Edison non e' cosi' fornito cosi' si e' abituati per esempio con Arduino YUN.
La soluzione deriva dalle AlexT's Edison Page, un repository non ufficiale che riporta un discreto numero di pacchetti di uso comune gia' in formato binario
Per abilitare questo repository si deve aggiungere al file /etc/opkg/base-feeds.conf le seguenti righe
-------------------------------
src/gz all http://repo.opkg.net/edison/repo/all
src/gz edison http://repo.opkg.net/edison/repo/edison
src/gz core2-32 http://repo.opkg.net/edison/repo/core2-32-------------------------------
si digita quindi
opkg update
(sul sito viene esplicitamente indicato di non usare opkg upgrade ma di configurare l'upgrade pacchetto per pacchetto pena la saturazione della rootfs)
Si possono quindi installare pacchetti come opencv e motion senza fatica
La soluzione deriva dalle AlexT's Edison Page, un repository non ufficiale che riporta un discreto numero di pacchetti di uso comune gia' in formato binario
Per abilitare questo repository si deve aggiungere al file /etc/opkg/base-feeds.conf le seguenti righe
-------------------------------
src/gz all http://repo.opkg.net/edison/repo/all
src/gz edison http://repo.opkg.net/edison/repo/edison
src/gz core2-32 http://repo.opkg.net/edison/repo/core2-32-------------------------------
si digita quindi
opkg update
(sul sito viene esplicitamente indicato di non usare opkg upgrade ma di configurare l'upgrade pacchetto per pacchetto pena la saturazione della rootfs)
Si possono quindi installare pacchetti come opencv e motion senza fatica
lunedì 6 giugno 2016
Moltiplicazione veloce per 10 in binario
Questo e' un sistema rapido per effettuare moltiplicazioni per 10 su un calcolatore binario ripresa da questo documento
L'idea e' quella di dividere la moltiplicazione per 10 come (numero*8)+(numero*2) che equivale ovviamento a numero numero*(8+2). Il vantaggio di questo procedimento e' che in con codificato binario le moltiplicazione per 2 (e per i suoi multipli) consistono semplicemente in uno spostamento verso sinistra dei bit.
Un esempio: moltiplichiamo 123x10
la codifica binaria di 123 e' 1111011
lo shift di un posto (moltiplicazione per due) e' 11110110
lo shift di tre posti (moltiplicazione per otto) e' 1111011000
la somma binaria di 11110110 + 1111011000 equivale a 10011001110 che corrisponde al risultato desiderato di 1230
Il vantaggio di questo sistema e' che in Assembler esiste un comodo apposito per lo shift binario a sinistra che e' ASL nel 6502 e SHL in x86
L'idea e' quella di dividere la moltiplicazione per 10 come (numero*8)+(numero*2) che equivale ovviamento a numero numero*(8+2). Il vantaggio di questo procedimento e' che in con codificato binario le moltiplicazione per 2 (e per i suoi multipli) consistono semplicemente in uno spostamento verso sinistra dei bit.
Un esempio: moltiplichiamo 123x10
la codifica binaria di 123 e' 1111011
lo shift di un posto (moltiplicazione per due) e' 11110110
lo shift di tre posti (moltiplicazione per otto) e' 1111011000
la somma binaria di 11110110 + 1111011000 equivale a 10011001110 che corrisponde al risultato desiderato di 1230
Il vantaggio di questo sistema e' che in Assembler esiste un comodo apposito per lo shift binario a sinistra che e' ASL nel 6502 e SHL in x86
mercoledì 1 giugno 2016
Sviluppo assembler su C64
Mi e' presa la voglia di tornare alle origini e programmare in assembler sul MOS 6502 (o meglio sul MOS 6510 del Commodore 64). Ovviamente il computer fisico e' in qualche discarica (o spero recuperato) e cerco di usare l'emulatore VICE
In modo, piu' o meno tradizionale, dopo aver avviato l'emulatore, si deve impiegare un assemblatore (nel caso Turbo Assembler per C64...con una curiosa omonimia con TASM Borland per x86) caricando l'immagine di un disco (preventivamente scaricat) con File/Attach Disk Image/Disk 8
con LOAD"$",8 e successivo LIST si ottiene il contenuto del disco
Si carica l'assemblatore con LOAD"*",8,1 ed al READY si digita SYS36864 entrando nella schermata nera di editing. Questo e' il semplice programma di test che stampa a video una stringa
programma in sintassi TASM
--------------------------------------------------
Per compilare il programma si deve usare la combinazione BackArrow+3 ma BackArrow non esiste sulla tastiera PC; si tratta del tasto piu' in alto a sinistra al di sotto del tasto di ESC (che nella tastiera italiana e' il backslash o barra rovescia)
s per start e si avvia il programma. Per rientrare nella fase di editing e' sufficiente ridigitare SYS 36864
E' comunque piuttosto noioso procedere nel modo classico ed e' molto piu' comodo usare C64 Studio (una IDE con allegato ACME un cross compiler 6502) e che permette di eseguire il programma lanciando autonomamente VICE
La differenza sostanziale tra i due metodi e' che usando C64 Studio si deve scrivere un preambolo in Basic che lancia poi il codice Assembler (in pratica una sola linea di codice BASIC che indichi un SYS49152 per passare il controllo al codice assembler...tale preambolo e' ralizzato con le sole righe *=$0801 ovvero la locazione di memoria dove risiede il compilatore BASIC e !basic.. non risulta necessario impostare *=$01000)
programma in sintassi ACME. Da notare come viene dichiarata la stringa
--------------------------------------------------
fra le altre cose con C64 Studio si puo' utilizzare anche direttamente Basic
In modo, piu' o meno tradizionale, dopo aver avviato l'emulatore, si deve impiegare un assemblatore (nel caso Turbo Assembler per C64...con una curiosa omonimia con TASM Borland per x86) caricando l'immagine di un disco (preventivamente scaricat) con File/Attach Disk Image/Disk 8
con LOAD"$",8 e successivo LIST si ottiene il contenuto del disco
Si carica l'assemblatore con LOAD"*",8,1 ed al READY si digita SYS36864 entrando nella schermata nera di editing. Questo e' il semplice programma di test che stampa a video una stringa
programma in sintassi TASM
--------------------------------------------------
* = $1000
!basic
ldx #$00
loop
lda message,x
sta $0400,x
inx
cpx #$04
bne loop
rts
message .text "luca"
--------------------------------------------------
Per compilare il programma si deve usare la combinazione BackArrow+3 ma BackArrow non esiste sulla tastiera PC; si tratta del tasto piu' in alto a sinistra al di sotto del tasto di ESC (che nella tastiera italiana e' il backslash o barra rovescia)
s per start e si avvia il programma. Per rientrare nella fase di editing e' sufficiente ridigitare SYS 36864
E' comunque piuttosto noioso procedere nel modo classico ed e' molto piu' comodo usare C64 Studio (una IDE con allegato ACME un cross compiler 6502) e che permette di eseguire il programma lanciando autonomamente VICE
La differenza sostanziale tra i due metodi e' che usando C64 Studio si deve scrivere un preambolo in Basic che lancia poi il codice Assembler (in pratica una sola linea di codice BASIC che indichi un SYS49152 per passare il controllo al codice assembler...tale preambolo e' ralizzato con le sole righe *=$0801 ovvero la locazione di memoria dove risiede il compilatore BASIC e !basic.. non risulta necessario impostare *=$01000)
programma in sintassi ACME. Da notare come viene dichiarata la stringa
--------------------------------------------------
;set program start address
* = $0801
!basic
ldx #$00
loop
lda message,x
sta $0400,x
inx
cpx #$04
bne loop
rts
message !scr "luca"
fra le altre cose con C64 Studio si puo' utilizzare anche direttamente Basic
ArduinoTheremin
Questo progetto e' stata soltanto una occasione per usare la libreria Mozzi e non puo' considerato completo e finito.
Con Mozzi e' possibile trasformare Arduino in un sintetizzatore usando semplicemente il pin 9 ed il Ground collegandoli ai pin di un jack audio da pcb. Fra le altre cose il segnale in uscita e' cosi' alto che puo' essere direttamente mandato in cuffia senza necessita' di amplificazione
L'idea e' quella di usare due sensori ultrasonici SR-04 per controllare la frequenza ed il volume. Il problema e' che Mozzi usa i timer di Arduino per la propria necessita' di produzione audio e quindi SR-04 non e' il componente piu' adatto per interfacciarsi a Mozzi
le frequenze sono scalate da 4 a 40 cm con frequenze da 100 a 660 Hz (la frequenza e' stata poi portata 4 ottave piu' alto) mentre il volume va da 0 al massimo passando da 4 a 40 cm
la base utilizzata deriva da questo sketch
---------------------------------------------------------
/*
This file uses a Ultrasonic Sensor code that was
modified from the a code found on:
http://winkleink.blogspot.ca/2012/05/arduino-hc-sr04-ultrasonic-distance.html
and modified codes from Mozzi examples and reference documentation.
*/
// Include Mozzi Classes
#include <MozziGuts.h>;
#include <mozzi_config.h>
#include <Oscil.h>;
#include <tables/sin1024_int8.h>;
#include <tables/saw2048_int8.h>;
#include <tables/cos2048_int8.h>;
#include <mozzi_rand.h>;
#include <LowPassFilter.h>;
#define CONTROL_RATE 64
Oscil <2048, AUDIO_RATE> osc(SAW2048_DATA); // Oscilator waveform
Oscil <COS2048_NUM_CELLS, CONTROL_RATE> filterMod(COS2048_DATA); // Low Pass Filter waveform
Oscil <2048, CONTROL_RATE> kvib(SAW2048_DATA); // Vibrato Waveform
LowPassFilter lpf;
// Ultrasonic Sensor Pins
int trigPin = 11;
int echoPin = 12;
// Ultrasonic Sensor Pins
int trigPin2 = 8;
int echoPin2 = 7;
byte volume;
void setup(){
Serial.begin(115200);
startMozzi(CONTROL_RATE);
//lpf.setResonance(20);
kvib.setFreq(16.5f);
filterMod.setFreq(1.3f);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(trigPin2, OUTPUT);
pinMode(echoPin2, INPUT);
}
void updateControl(){
// Distance Sensor
int duration, distance;
digitalWrite(trigPin, HIGH);
delayMicroseconds(100);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = (duration/2) / 29.1;
int freq = map(distance, 4, 40, 100, 660);
/*
C = 261
C#= 277
D = 293
D#= 311
E = 329
F = 349
F#= 369
G = 391
G#= 415
A = 439
A#= 466
B = 493
C = 523
*/
int duration2, distance2;
digitalWrite(trigPin2, HIGH);
delayMicroseconds(100);
digitalWrite(trigPin2, LOW);
duration2 = pulseIn(echoPin2, HIGH);
distance2 = (duration2/2) / 29.1;
volume = map(distance2, 4, 40, 0, 255);
byte cutoff_freq = 100 + filterMod.next()/2;
lpf.setCutoffFreq(cutoff_freq);
osc.setFreq(freq*2);
//float depth = 1; // vibrato depth
//float vibrato = depth * kvib.next();
/*if (rand(CONTROL_RATE/2) == 0) // Low Pass Filter Frequency
{
filterMod.setFreq((float)rand(255)/64);
}
byte cutoff_freq = 100 + filterMod.next()/2;
lpf.setCutoffFreq(cutoff_freq);
if(xRead > 500){
osc.setFreq(freq);
}
else if(xRead < 500){
osc.setFreq(freq*4);
} */
}
int updateAudio(){
char audio = (lpf.next(osc.next())*volume)>>8;
return (int) audio;
}
void loop(){
audioHook();
}
Con Mozzi e' possibile trasformare Arduino in un sintetizzatore usando semplicemente il pin 9 ed il Ground collegandoli ai pin di un jack audio da pcb. Fra le altre cose il segnale in uscita e' cosi' alto che puo' essere direttamente mandato in cuffia senza necessita' di amplificazione
L'idea e' quella di usare due sensori ultrasonici SR-04 per controllare la frequenza ed il volume. Il problema e' che Mozzi usa i timer di Arduino per la propria necessita' di produzione audio e quindi SR-04 non e' il componente piu' adatto per interfacciarsi a Mozzi
le frequenze sono scalate da 4 a 40 cm con frequenze da 100 a 660 Hz (la frequenza e' stata poi portata 4 ottave piu' alto) mentre il volume va da 0 al massimo passando da 4 a 40 cm
la base utilizzata deriva da questo sketch
---------------------------------------------------------
/*
This file uses a Ultrasonic Sensor code that was
modified from the a code found on:
http://winkleink.blogspot.ca/2012/05/arduino-hc-sr04-ultrasonic-distance.html
and modified codes from Mozzi examples and reference documentation.
*/
// Include Mozzi Classes
#include <MozziGuts.h>;
#include <mozzi_config.h>
#include <Oscil.h>;
#include <tables/sin1024_int8.h>;
#include <tables/saw2048_int8.h>;
#include <tables/cos2048_int8.h>;
#include <mozzi_rand.h>;
#include <LowPassFilter.h>;
#define CONTROL_RATE 64
Oscil <2048, AUDIO_RATE> osc(SAW2048_DATA); // Oscilator waveform
Oscil <COS2048_NUM_CELLS, CONTROL_RATE> filterMod(COS2048_DATA); // Low Pass Filter waveform
Oscil <2048, CONTROL_RATE> kvib(SAW2048_DATA); // Vibrato Waveform
LowPassFilter lpf;
// Ultrasonic Sensor Pins
int trigPin = 11;
int echoPin = 12;
// Ultrasonic Sensor Pins
int trigPin2 = 8;
int echoPin2 = 7;
byte volume;
void setup(){
Serial.begin(115200);
startMozzi(CONTROL_RATE);
//lpf.setResonance(20);
kvib.setFreq(16.5f);
filterMod.setFreq(1.3f);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(trigPin2, OUTPUT);
pinMode(echoPin2, INPUT);
}
void updateControl(){
// Distance Sensor
int duration, distance;
digitalWrite(trigPin, HIGH);
delayMicroseconds(100);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = (duration/2) / 29.1;
int freq = map(distance, 4, 40, 100, 660);
/*
C = 261
C#= 277
D = 293
D#= 311
E = 329
F = 349
F#= 369
G = 391
G#= 415
A = 439
A#= 466
B = 493
C = 523
*/
int duration2, distance2;
digitalWrite(trigPin2, HIGH);
delayMicroseconds(100);
digitalWrite(trigPin2, LOW);
duration2 = pulseIn(echoPin2, HIGH);
distance2 = (duration2/2) / 29.1;
volume = map(distance2, 4, 40, 0, 255);
byte cutoff_freq = 100 + filterMod.next()/2;
lpf.setCutoffFreq(cutoff_freq);
osc.setFreq(freq*2);
//float depth = 1; // vibrato depth
//float vibrato = depth * kvib.next();
/*if (rand(CONTROL_RATE/2) == 0) // Low Pass Filter Frequency
{
filterMod.setFreq((float)rand(255)/64);
}
byte cutoff_freq = 100 + filterMod.next()/2;
lpf.setCutoffFreq(cutoff_freq);
if(xRead > 500){
osc.setFreq(freq);
}
else if(xRead < 500){
osc.setFreq(freq*4);
} */
}
int updateAudio(){
char audio = (lpf.next(osc.next())*volume)>>8;
return (int) audio;
}
void loop(){
audioHook();
}
Iscriviti a:
Post (Atom)
Debugger integrato ESP32S3
Aggiornamento In realta' il Jtag USB funziona anche sui moduli cinesi Il problema risiede nell'ID USB della porta Jtag. Nel modulo...
-
In questo post viene indicato come creare uno scatterplot dinamico basato da dati ripresi da un file csv (nel dettaglio il file csv e' c...
-
Questo post e' a seguito di quanto gia' visto nella precedente prova Lo scopo e' sempre il solito: creare un sistema che permet...
-
La scheda ESP32-2432S028R monta un Esp Dev Module con uno schermo TFT a driver ILI9341 di 320x240 pixels 16 bit colore.Il sito di riferiment...