Ik speelde al een tijdje met het idee op een uur signaal te maken voor de klok.
Ik zocht relatief gemakkelijke methode om geluid af te spelen mbv een PIC. Ik heb er aan gedacht om met bv een winbond ChipCorder ic een sample af te spelen, maar tijdens een zoektocht op iternet kwam ik de volgende paginas tegen:
http://www.romanblack.com/picsound.htm
http://www.romanblack.com/btc_alg.htm
Hier staat een methode beschreven om op een eenvoudige manier geluid uit een pic te halen.
Aangezien ik deze methode niet op GoT terug kan vinden is hier een soort van [HOWTO]
Misschien dat dit een apart topic waard is, maar dat laat ik over aan een Modje
Zo zou het ongeveer zo moeten werken:
Een .wav bestand wordt volgens speciaal algoritme omgezet naar een 'look-up' tabel (een enorme lijst met waardes die gereturned worden).
De PIC gaat één voor één de bytes van het tabel af, en schuift de bits langs een data pin waar een RC netwerk aan hangt.
Bij het encoderen rekent het algoritme de geluidsgolven door op basis van de Tc van het RC filter. Op deze manier kan je met een 1-bit datastroom een geluidsfragment benaderen.
Het algoritme kan ook ingesteld worden op een 1.5-bit datastroom. Voor zover ik het door heb, is de bedoeling is dan dat de waarde van de data pin wordt doorgeschoven op een andere uitgang.
Dan wordt de vorige waarde van de pin in de berekening, en door een extra data pin te gebruiken kan.
Na nog wat zoeken kwam ik ook een site tegen, waar ene Bert van Dam deeze methode heeft gebruikt in JAL (1-bit):
http://members.home.nl/b.vandam/lonely/pagina47.html (klik onderaan op de link om de frames goed te krijgen)
Ik heb eerst geprobeerd om een look-up table te maken in Mikrobasic, maar dat lukt niet helemaal.
Daarom heb ik maar een poging gedaan in pic assembly.
Ik had alleen nog nooit in assembly geprogrameerd, dus dat heb ik mezelf een beetje aan moeten leren.
(ik heb de knipperende led maar overgeslagen

)
Deze methode werkt als volgt:
Het door Roman Black gemaakte programma maakt van een .wav file een .asm file met de data aan
Die data gaat dan in een enorme 'look-up table' (meer info:
Microchip technote AN556
Software in de PIC moet dan het tabel aanspreken en op het juiste moment Data pinnen aan/uit zetten.
De hoofdlus doet het volgende:
- Byte ophalen uit het tabel
- 8x:
- porta uitlezen om de waarde van de vorige bit te bepalen
- nieuwe bit ophalen
- Wachten op interrupt
- nieuwe waarde naar PORTA schrijven
- De byte uit het tabel verschuiven, zodat de volgende bit op de positie van de vorige komt
Als het hele tabel is doorlopen begint de PIC weer aan het begin.
Je kan het laatste 'retlw' commando vervangen door b.v. sleep of een goto
Het is een deel knip en plak werk van o.a. piclist.org:
Dit heb ik als basis genomen voor mijn tabel:
http://www.sxlist.com/techref/microchip/bigtable.htm
http://www.sxlist.com/techref/microchip/tables.htm
Ik kan niet zeggen dat ik alles begrijp wat er gebeurt, maar ik heb er wel iets werkends uit gekregen.
Wat te doen om dit werkend te krijgen
Dit voorbeeld werkt op de 16F628a, misschien moet er iets veranderd worden om het op andere pics aan de praat te krijgen.
Deze PIC heeft maar 2048 Kwords programma geheugen. Voor mij is het geen probleem omdat ik maar een sample van ongeveer 2 seconden nodig heb, maar voor langere fragmenten moet je al snel naar 8 Kwords (of een losse eeprom)
In mijn PIC processor heb ik als ik bij locatie 0x0100 begin nog ruimte voor 7 blokken van 256 bytes
op 7812.5 bit/s is dat ongeveer 1.8 seconde
• Download en unzip
de BTc sound encoder
•
Zoek of maak een wave file.
Ik heb een sample met de Winamp diskwriter uit een aflevering van een serie gehaald en de trial versie van Goldwave gebruikt om hem te bewerken.
•
Resample het geluidsfragment naar een geschikte bitrate, en sla het op als 'PCM unsigned 8-bit mono'
Ik heb de software getest op 15625 en 7812.5 Hz. (van de laatste ben ik niet zeker of de halve hz ook is meegnomen door goldwave en de BTc software)
Deze bitrates zijn makkelijk te maken met de timer van een PIC. De pic draait op de interne oscillator op 4 MHz. Iedere instructie cycle (Fosc/4) wordt TMR0 opgehoogd. bij '256' geeft de timer een overflow interrupt. (bij 10 ns per instructie is dat dus met een frequentie van 3906,25 Hz)
Als je voor een lagere bitrate kiest moet je met de prescaler gaan werken, een hogere frequentie kan bereikt worden door een waarde naar het TMR0 register te schrijven.
In de code onderaan deze post staat in de interrupt service routine:
movlw b'10000000'
movwf TMR0
Dit is voor 7812.5 Hz
Als je een bitrate van 15625 kiest dan moet het "movlw b'11000000'" worden
•
Open het .wav bestand in de BTc encoder.
Kies het 1.5 bits algoritme en BTc32 als fineness
Je kan het oorspronkelijke geluidsfragment afspelen en een benadering van hoe het klinkt op uit PIC.
Kies in het file menu: export PIC assembler file en sla het bestand op.
• Maak het asm bestand klaar om te compilen[/u]
In Microchip MPLAB:
- Maak een nieuw project aan en voeg de juiste 'Linker' script en Header file toe.
- Voeg het door BTc gegenereerde bestand toe, en bewerk het als volgt:
- Zoek alle "org (" en vervang met "org 0x0" (zonder "" )
- Zoek alle " *256)" en vervang met "00"
Er hoort nu bv "org 0x0100" te staan
(dit gaat waarschijnlijk niet helemaal goed als je meer dan 15 blocks hebt )
- Verwijder alles wat niet in het geheugen past
Als je bij 0x100 begint, is dat in de 16f628a alles vanaf block 8
- Verwijder het voorbeeld tabel uit de code[/u]
- Voeg op de eerste retlw b'xxxxxxxx' regel de tabel naam TStart toe
- Plak de onderstaande code aan het begin van het bestand
- Pas eventueel de de waarde aan die naar TMR0 geschreven wordt (afhankelijk van oscillator en bitrate)
- Pas eventueel de config bits, ik gebruik interne oscillator op 4 MHz en geen ISP
- Zorg dat "end" helemaal onderaan staat
•
Maak de hex file, en programmeer de PIC processor
•
Bouw een standaard experimenteer opstelling op een breadboard
- maak het schema zoals gegenereerd in het BTc bestand op pin 1 en 2 (PORTA,2 en PORTA,3)
- sluit een standaard pc speaker aan tussen de 'analoge ouput' en de gnd
•
Nu zou je een werkende opstelling moeten hebben waar geluid uit komt.
Verwacht alleen geen muziekale hoogstandjes, deze methode is vrij grof.
Je kan een beetje spelen met de waardes van de weerstanden en de condensator om het geluid beter te krijgen.
Nog een paar opmerkingen
Als de BTc sound encoder erg hoge weerstand waardes opgeeft kan je er een opamp achter zetten.
Ik heb een TL 072 gebruikt. Die kan je aansluiten volgens het schema op de site van bert van dam, maar dan moet niet pin 7 maar pin 8 aan 5v, en pin 1 is in plaats van pin 6 de output (die ook terug gaat naar pin 2)
Zoals Bert van Dam op zijn site opmerkt kan er een irritante geluidsgolf ontstaan door de rijen met afwisselende enen en nullen. Soms helpt het om alle '10101010' en '01010101' bytes te vervangen door '00000000'
Ook lijkt het gewoon te werken als je de condensator weghaalt
En nu even terug naar het onderwerp:
Ik heb alle ledjes in de klok vervangen voor felle leds (ik weet de licht opbrengst niet maar het scheelt een hoop) De leds zelf heb ik een beetje opgeschuurd (in één righting) om het licht beter te spreiden in de richting van een segment
Zoals ik in het begin al zei, was de bedoeling om een geluidsfragment af te spelen als uur signaal.
De pics praten nog niet met elkaar, maar de bedoeling is om het signaal één of twee keer af te spelen als de klok van uur verspringt.
Dit is het resultaat:
http://www.scrap.cistron.nl/Picklok/geluid.mpg
Het moet dus het geluidje van '24' zijn, maar de kwaliteit valt nogal tegen op 7812 Hz
Ik heb ook nog een vraagje, wanneer gebruik je 'equ' en wanneer 'set' als je een variable declareerd in mplab?
Dit is de assembly code voor MPLAB:
GAS:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
| ; BTc 1.5 bit sound playback from PIC program memory
; Modified example from: http://www.sxlist.com/techref/microchip/tables.htm
list p=16F628a
#include "p16f628a.inc"
__config 3f18 ; int osc, alles uit
OffsetH EQU 0x20 ; Hoge byte voor Tabel rij
OffsetL EQU 0x21 ; Lage byte voor Tabel rij
Bitstream EQU 0x22 ; Byte uit tabel
COUNT EQU 0x23 ; Teller voor For..Next
Interrupt EQU 0x24 ; Interrupt check
BTc EQU 0x25 ; Tijdlijke opslag voor PORTA bits
; the fcall macro
; by Roger Froud of Amytech Ltd.
;(execution starts here)
fcall macro subname ; uit voorbeeld van de piclist, schijnt geen effect te hebbenm op deze PIC
local here
lcall subname ; set PCLATH correctly
pagesel here ; set PCLATH correctly
here:
endm
RST code 0x0000
GOTO Start
INT code 0x0004 ;Interrupt Vector
GOTO ServInt ;Jump to service interrupt
; main:
isr org 0x008 ;Interrupt Service Routine
ServInt
MOVLW b'10000000' ; schrijft een waarde voor de bitrate naar de timer
banksel TMR0
MOVWF TMR0
banksel Interrupt ;Wis interrupt check
BSF Interrupt, 0
banksel INTCON ;Select INTCON Bank (0)
BCF INTCON, T0IF ;Clear overflow flag
RETFIE ;Return from interrupt
Start ;configuratie
MOVLW 8
banksel OPTION_REG
MOVWF OPTION_REG ;Timer0 prescaler naar WDT (niet nodig)
MOVLW 7
banksel CMCON
MOVWF CMCON ;Comperatoren uit
banksel TRISA ; PORTA is uitgang
CLRF TRISA
banksel OffsetH ; Wis alle variabelen
CLRF OffsetH
CLRF OffsetL
CLRF Bitstream
CLRF COUNT
CLRF Interrupt
CLRF PORTA
banksel INTCON
BSF INTCON, GIE ;Enable Global Int's
BSF INTCON, T0IE ;Enable Timer0 Int
SoundLoop
fcall Table ;Roep het tabel aan (fcall is volgens de compiler niet nodig?)
banksel Bitstream ; W komt nu uit het tabel
MOVWF Bitstream ;
MOVLW 0x08 ; 8x loop
MOVWF COUNT
Loop_bitstream: ;Begin loop
banksel BTc
CLRF BTc
BTFSC PORTA,3 ; schuif waarde van porta.3 door op
BSF BTc,2
BTFSC Bitstream, 7 ; Bekijk de volgende bit, en zet indien nodig
Bsf BTc,3 ; porta.3 op hoog
BCF Interrupt,0
waitforinterrupt: ; Wachten
BTFSS Interrupt,0
GOTO waitforinterrupt
MOVFW BTc
MOVWF PORTA
RLF Bitstream,1 ; shift is maar 7x nodig
DECFSZ COUNT,1
GOTO Loop_bitstream
INCF OffsetL , 1 ; add 1 to data pointer
SKPNZ
INCF OffsetH , 1
GOTO SoundLoop
;NoUp ;Uit het voorbeeld van piclist (niet getest)
; MOVLW Low(d'1792') ;Hiermee zou je moeten kunnen bepalen of je
; XORWF OffsetL,W ;door het tabel heen ben als je niet al je geheugen gebruikt
; SKPNZ
; GOTO SoundLoop
; MOVLW High(d'1792')
; XORWF OffsetH,W
; SKPNZ
; GOTO SoundLoop
; GOTO Start
Table MOVLW HIGH (TStart)
ADDWF OffsetH,W
MOVWF PCLATH
MOVLW LOW (TStart)
ADDWF OffsetL,W
SKPNC
INCF PCLATH,F
MOVWF PCL
; Hieronder staat het door BTc gegenereerde tabel
;=====================================================
; AUTO CREATED FILE made by Windows BTc Sound Encoder
; v1.1 Copyright 2002 - Roman Black
;
; Hippyware.
; www.RomanBlack.com
;=====================================================
;
; File Details:
; Size 15360 bits (1920 bytes)
; Sound encoded at 7812 bits/sec
; using BTc32 1.5bit Algorithm to be decoded on
; the following circuit:
;
;
; R = 18324 ohms
; each 2R = 36648 ohms
;
;
; Digital ----------2R-----,
; |
; Digital ----------2R-----*----- Analogue
; | out
; |
; |
; C = 0.22 uF
; |
; |
; |
; Gnd
;
;
;=====================================================
; Bitstream data is in PIC .asm table format,
; in blocks of 256 bytes.
;
; Bits are played from left to right, from ms_bit to
; ls_bit.
;=====================================================
;---------------------------------------------------
org 0x0100 ; block = 1
;---------------------------------------------------
;------------------------- 0
TStart retlw b'00000000' ; aa
retlw b'00000000' ; aa
retlw b'00000000' ; aa
retlw b'00000000' ; aa
retlw b'00000000' ; aa
retlw b'00000000' ; aa
retlw b'00000000' ; aa
retlw b'00000000' ; aa
;------------------------- 8
retlw b'00000000' ; aa
retlw b'00000000' ; aa
retlw b'00000000' ; aa
retlw b'00000000' ; aa
; KNIP Hier staat het enorme tabel
retlw b'01010101' ; 55
retlw b'01010101' ; 55
retlw b'01010101' ; 55
;------------------------- 1784
retlw b'01010101' ; 55
retlw b'01010101' ; 55
retlw b'01010101' ; 55
retlw b'01010101' ; 55
retlw b'01010101' ; 55
retlw b'01010101' ; 55
retlw b'01010101' ; 55
retlw b'01010101' ; 55
;---------------------------------------------------
;
; End of file.
;
;---------------------------------------------------
end |