Eeprom 24cxxx und 25cxxx
Ich suche nach einer Möglichkeit für das Abspeichern von neuen "Songs" für die
Objekte: Droschke, Kurbelrad, Sackklangkarre, MusikHomeTrainer u.a.
Eine Idee wäre, die Midi-Songs von einer SD-Card auslesen zu lassen und diese auf
den Eeprom zu übertragen.
Eine andere Idee: Per Midiox Mididatei als Sysex überspielen.
Die Größe eines Midi-Songs für meine Objekte bewegt sich zwischen: 4KB und 26KB
Für 3 "Songs" bei den MusikHomeTrainern bräuchten wir dann ca. 75KByte
Angaben beim Eeprom in KBit. 26KB sind ca. 208KBit. 1MBit sind dann 125KByte.
Lieber bei Reichelt kaufen. Muss lange suchen bei Aliexpress!
Adressen
Eine Adresse ist 24Bit groß.
Niedrigste: Hx000000
Höchste: Hx01FFFF = 131.071
131.071 Byte = 1.048.568 Bit = 1.048 KB = 1 MB
Habe im Datenblatt keine Angaben über die Adressen für die Seiten an sich gefunden.
Eine Seite ist 256 Byte groß. Erste Adresse ist 0. Also geht die erste Seite bis ByteNr 255 = FF.
Die zweite Seite beginnt dann bei 100 und endet bei 1FF.
Die dritte Seite beginnt bei 200 usw.
Seite 1 - 00000 bis 000FF - 0 bis 255
Seite 2 - 00100 bis 001FF - 256 bis 511
Seite 3 - 00200 bis 002FF - 512 bis 767
Seite 4 - 00300 bis 003FF - 768 bis 1023
...
Seite 511 - 1FF00 bis 1FFFF - 130.816 bis 131.071
Also Startadresse für die jeweilige Seite ist
Seitennummer mal 256. Wobei Seitennummer bei
Null beginnt. Also 0*256=0 - 1*256=256 - 2*256=512 - 3*256=768 usw. - 511*256=130.816
Es gibt also 512 Seiten -- 0 bis 511.
Anschlüsse
Hold = H = Chip aktiv. Kann uC nutzen, um andere Aufgaben zu machen. Oder bei Doppelnutzung
der Datenleitungen für einen anderen Chip
WP = Hi, ansonsten ist Write blockiert.
CS ---- Low = Aktiv.
AVR Code
Ein Byte
Ein Byte einschreiben und wieder auslesen über eine LCD-Anzeige.
uint8_t
// Kommentar
#define
Seitenweise speichern
ist verworfen, da ich schon vor dem Speicherprozess die Mididatei "reinigen" will.
Es sollen im Eeprom nur die Anweisungen: NoteOn und NoteOff, sowie die Zeitangaben (DeltaTime) gespeichert werden.
Das macht dann auch das Rückwärtsspielen einfacher.
Byteweise speichern
MidiOx sendet Midi-Datei als Sysex. uC "fängt diese auf" und speichert sie vorerst in das
Array
Daten[]
Parall dazu werden dann die Bytes aus dem Array
Daten[]
ausgelesen und es
wird entschieden, ob sie für das Vor- und Rückwärtsabspielen des "Songs" nötig sind.
Erst danach kommen die nötigen Bytes in den Eeprom - d.h. im Eeprom sind fast alles nur Notenwerte und -Anweisungen.
Nun die Schritte:
1.) Die Arrayvariablen fangen alle mit 0 an. Beim 23. Byte beginnen die Abspieldaten. Davor kann man einzelne
Werte, wie Tempo und Takt in den Eeprom des uC abspeichern.
2.) IR ist scharf gestellt und wartet auf MidiIn Daten - RxD. Die Variable PoiWriteUartData wird erhöht.
ISR(USART_RXC_vect)
{
uint8_t
a = UDR;
//Neuen empfangenen Wert in Array einschreiben
UartData[PoiWriteUartData] = a;
if
(PoiWriteUartData < (MaxUartData-1)) PoiWriteUartData++;
else
PoiWriteUartData = 0;
// Pointer neu setzen
}
Die eingehenden Daten ganz in Ruhe in der normalen Routine auswerten:
void RxMidiDaten(void)
{
if
(PoiReadUartData != PoiWriteUartData)
{
uint8_t
temp = UartData[PoiReadUartData];
// angekommendes Midibyte zwischen speichern
if
(PoiReadUartData < (MaxUartData-1)) PoiReadUartData++;
else
PoiReadUartData = 0;
// Pointer ggf. erhöhen oder zurück auf Null
...
}
}
Größen: Eeprom und AVR
Eeprom
Größe
Schnitt-
stelle
Page-Größe
in Byte
Zugriffszeit
in ns
Kosten 2026
25LC1024
1MBit = 128KB
SPI
256
100
Rei: 1,55€ Ali ???
24LC1025
1MBit = 128KB
I2C
256
900
Rei: 1,65€
25LC512-I/P
512KBit = 64KB
SPI
128
100
Rei:2,95 Ali:0.37
24C512BN
512KBit = 64KB
I2C
128
550
Rei: 0,95€
24AA512
512KBit = 64KB
I2C
128
900
Rei: 1,28€
25LC256-I/P
256KBit = 32KB
SPI
64
100
Rei: 0,95€
25AA256-I/P
256KBit = 32KB
SPI
64
250
Rei: 1,15€
24FC256
256KBit = 32KB
I2C
64
400
Rei: 1,59€
24C256BN
256KBit = 32KB
I2C
64
550
Rei: 0,86€
Es wird wohl der 25LC1024 werden mit SPI - 2,5..5,5V
Zum Vergleichen die SRAM und der PROG Speicher
Name uC
SRAM in KByte
PROG in KByte
EPROM in Byte
Preis Reichelt
Preis Aliexpress
ATM 16 / ATM168
1
16
512
3,20 / 3,10
1,49 / 2,25
ATM 32 / 328
2
32
1024
3,70 / 3,29
2,53 / 1,49
ATM 644
4
64
2048
5,83
nicht da
ATM 1284
16
128
4096
8,80
10,68
Für unsere Zwecke würden ATMega644 oder ATMega1284 reichen, notfalls noch ATMega32 oder 328.
4..26KB pro Song. Im Programmspeicher wäre dafür Platz. So ist es ja bis jetzt.
Beispiel:
Blaue MusikHomeTrainer für Atonor.
Progspeicher von ATM644 mit 3 Songs: 88.2% gefüllt
Speicherplatz Midisongs: F2_Bizet_Jeux12_.h = 69kB, MozartSatz1.h = 59kB, Traeumerei2.h = 15kB
Mididateien sind kleiner: bizet_jeux_12_(c)yogore = 17kB, MozartSatz1 = 29kB, Traeumerei2 = 6kB
Gesamt Songs h-Files = 143kB.
Alle Midi-Files = 52kB
Speicherplatz mit fast keinen Midifiles: 18,3%
88,2% ProgSpeicher - 18.3% Prog ohne Midi = 69,9% übrig für Midi =
44,7kB für Midifiles - etwas zu wenig, könnte aber hinkommen.
Lesen
So lange CS unten bleibt, wird die Adresse um jeweils eins erhöht und das nächste Byte
kann gelesen werden. Wenn die Adresse den höchsten Wert hat, geht es von vorn wieder los.
Ein Loop also. Beendet wird das Lesen, wenn CS wieder auf Hi geht.
Löschen
Es kann eine Seite, ein Sektor oder der ganze Chip gelöscht werden.
Achtung: Zuvor muss das WREN (Write enable) gesendet werden.
Beispiel: Chip löschen:
Zuerst WREN senden! 0000 0110
Dann: Chip Erase. 1100 0111
Midi-Datei
Auf althergebrachte Art und Weise mit
PoiRead
und
PoiWrite
.
(Man kann das auch mit "richtigen" Pointern machen)
PoiWrite wird immer dann erhöht, wenn ein Midibyte über die IR-Routine ausgelesen wird.
PoiRead wird erhöht, wenn ein Byte ausgelesen wird. Nach Auswertung kommt es dann ggf. in den Eeprom. FF u.a. Nachrichten sollen
gar nicht erst in den Eeprom eingeschrieben werden.
Dann werden PoiRead und PoiWrite verglichen und der Eeprom wird aufgefüllt.
Da nun aber die Pages des Eeproms beim Weglassen von Midi-Befehlen weniger beschrieben werden, kann
man nur umständlich die Pages korrigieren, denn kein Eep Byte Schreibplatz soll leer bleiben bis zum Ende des Midi-Files.
Größe Daten, auf die die Pointer zugreifen: Jetzt 200 Bytes, könnten aber auch mehr sein. -- probieren
SRAM ATMega8 / ATM16 / ATM168 - 1000Bytes.
SRAM ATM32 /328 - 2000Bytes.
SRAM ATM664 - 4000Bytes
Prozedur:
1.) Midi-Datei wird als SysEx gesendet. Die IR-Routine "Empfang" schreibt jedes Byte in das Array
Daten[]
ein.
2.) Wenn die beiden Pointer ungleich sind, wird das gelesene Byte abgefragt und auf "Unsinnigkeit" geprüft.
Angaben zu Tempo und Aufteiung extra speichern: Die ersten 14 Midi-Bytes
77 84 104 100 0 0 0 6 0 0 0 1 4 0
Byte 1-4
77 84 104 100
MThd
Byte 5-8
0 0 0 6
es folgen 6 Bytes - immer 6
Byte 9 und 10
0 0
00=Single Track - nur das verwenden wir, alle Daten liegen auf
einer einzigen Spur. 1 = Multiple Tracks. 2 = Multiple unabhängig
Byte 11 und 12
0 1
Gesamtzahl der Spurenblöcke
Byte 13 und 14
4 0
Ticks pro Viertelnote
Tempo bei:
FF 51 03 07 A1 20
07A120 = 500.000 Mikrosekunden pro Viertelnote.
BPM: 60.000.000 / 500.000 = 120
3.) Beim Lesen der SysEx Bytes, Daten ignorieren und nicht imm Eeprom speichern
SysEx - F0 .. FF x Folgebytes z.B.
255 84 5 0 0 0 0 0 0
Letztes Byte ist Zeitbyte
ProgChange-Daten: C0..CF 192 bis 207 - 2 Folgebytes z.B.
192 0 0
Letztes Byte ist Zeitbyte
Polyphon Pressure A0..AF 160 bis 175 - 3 Folgebytes
Control Change B0..BF 176 bis 191 - 3 Folgebytes
Channel Pressure D0..DF 208 bis 223 - 2 Folgebytes
Pitch Bend E0..EF 224 bis 239 - 3 Folgebytes
4.) Gelesene Bytes auswerten, um nur Notenwerte speichern zu müssen. Dabei Notenwerte ggf. auffüllen, also keine
Kurznotation.
Anstelle von:
144 69 62 0 54 72 131 74
die 144 dazu
setzen
144 69 62 0 144 54 72 131 74
(fett = Zeitwerte)
Schreiben
Vor jedem Schreibbefahl muss WREN gesetzt werden !
Es muss unbedingt dieser Befehl abgeschlossen werden mit CS=Hi !!!
Vorherige Daten werden beim Schreiben automatisch gelöscht. Das Löschen verheriger Werte muss
nicht extra erfolgen !!!
Nun das CS wieder runter setzen und mit dem Schreiben beginnen.
Übertragen wird: Der WRITE-Befehl sowie die 24-Bit-Adresse (wobei die sieben höchstwertigen
Bits/MSBs als „Don’t-Care“-Bits gelten, da die höchste Adresse:01FFFF ist, also das letzte
Byte nicht verwendet wird!) und anschließend die zu schreibenden Daten.
Es können bis zu
256 Bytes an das Bauteil gesendet werden, bevor ein Schreibzyklus
erforderlich ist. Die einzige Einschränkung besteht darin, dass sich alle Bytes
innerhalb derselben Seite befinden müssen. Bei Schreibvorgängen mit weniger als 256 Bytes
werden die Daten im verbleibenden Teil der Seite zusammen mit den zu schreibenden
Datenbytes aufgefrischt.
Wird eine Seite mit zu vielen Bytes beschrieben, tauchen diese auf der gleichen Seite
am Anfang wieder auf, nicht auf der nächsten Seite.
Am Ende eines Schreibzyklus wird WREN zurück gesetzt.
Ein Byte schreiben:
Eine Seite schreiben:
Am Ende kann man das "Schreiben" wieder ausschalten mit WRDI.
SPI - Kommandos
8-bit instruction register - zu erst.
SI wird übernommen, wenn CLK von Lo auf Hi geht.
Name
Wert Hex
Wert Dez
Beschreibung
READ
0000 0011
3
Liest die Daten aus bei angewählter Adresse.
WRITE
0000 0010
2
Schreibt Daten an ausgewählter Adresse ein.
WREN
0000 0110
6
Schaltet das Schreiben ein.
WRDI
0000 0100
4
Schaltet das Schreiben aus.
RDSR
0000 0101
5
Read Status Register
WRSR
0000 0001
1
Write Status Register
PE
0100 0010
66
Page erase - löscht eine Seite.
RDID
1010 1011
171
Chip wacht auf und gibt ID zurück
DPD
1011 1001
185
Chip schläft ein - Power down Mode