• Welcome to Schneider / Amstrad CPC Forum.
Welcome to Schneider / Amstrad CPC Forum. Please login.

17. April 2026, 09:09:20

Login with username, password and session length

Shoutbox

TFM

2024-04-08, 20:42:44
Happy Sonnenfinsternis!  :)

TFM

2024-01-15, 17:06:57
Momentan billige Farbbänder auf Ebay für PCW

Devilmarkus

2023-07-09, 10:37:40
Zweiter 👋😂🤣

TFM

2023-06-13, 14:21:49
Sommerloch!

Recent

Members
Stats
  • Total Posts: 12,834
  • Total Topics: 1,528
  • Online today: 215
  • Online ever: 1,724
  • (16. January 2020, 00:18:45)
Users Online
Users: 1
Guests: 157
Total: 158

157 Guests, 1 User
xesrjb

LambdaSpeak CPC Sprach-Synthesizer, Sample Player, RTC, MP3, UART Erweiterung

Started by LambdaMikel, 01. May 2017, 09:41:34

Previous topic - Next topic

0 Members and 11 Guests are viewing this topic.

Rennert

Ich nehme eins ohne Click to Speech  :D

LambdaMikel

#256
OK, es gibt eine kleinere Verzögerung....

zhulien aus dem anderen CPC-Board hat mich angeregt, doch noch die Schlafende Serielle (klingt fast nach Raumschiff Orion, oder?) freizusetzen (er will so ein billiges 4 $ MP3-Modul damit steuern... s. Bild - getestet habe ich es mit dem alten Emic 2, der auch ein USART-Gerät ist), jetzt muss ich noch ein bisschen an der Firmware arbeiten für den neuen Modus, und die PCBs müssen natürlich auch noch wieder neu... und wir haben noch 2 mehr DIP-Schalter, da links / rechts Audio-Ausgang von der Klinke nun auch in den CPC SND-Pin gespeist werden kann, zur Konsumierung durch den internen CPC-Lautsprecher und Verstärker.  Aber ein/ausschaltbar, wie gesagt. Ansonsten ist es aber fertig  :zunge0020: Also, es dauert noch 2 Wochen.

[CPCEmulator]https://youtu.be/E_u7NzCXM1k[/CPCEmulator]

Na ja, gut dass der Lötkolben noch heiß war! Immer wenn man denkt, jetzt hat man fertig, kommt doch noch wieder einer mit was  :D
Aber ist ja gut so!

TFM

Neue Funktionen sind immer gute Neuigkeiten.  :00008351:
Lass Dir ruhig Zeit, so dass es am Ende auch alles gut funktioniert.  :smiley027:
TFM of FutureSoft
http://www.futureos.de --> Das Betriebssystem FutureOS (Update: 24.12.2025)
http://futureos.cpc-live.com/files/LambdaSpeak_RSX_by_TFM.zip --> RSX ROM für LambdaSpeak (Update: 29.01.2025)

LambdaMikel

#258
OK, serielle Schnittstelle funktioniert, nun in beide Richtungen.

Ich habe testweise mit dem Emic 2 (ein USART device) in beide Richtungen kommuniziert, ueber ein BASIC-Programm. Die LambdaSpeak Firmware hat intelligente Befehle zum Senden und Empfangen ueber das USART (gepuffert).

Ich habe mir auch so ein FTDI-Kabel bestellt, damit kann ich auch PC-Terminal testen.

PCBs kommen naechste Woche, dann ist es fertig.

Hier mal eine Frage:
wie sieht ein maximal praktische Interface zum Empfangen von USART bytes aus?
Bisher habe ich:

- lese <n> Bytes vom USART
- lese Bytes vom USART bis <byte> empfangen (CR oder LF oder 0 oder...)
- lese Bytes vom USART fuer <n> Millsekunden

Die Bytes werden autark vom LambdaSpeak gelesen und gepuffert und koennen dann sukzessive vom CPC ausgelesen werden, indem man ein Kontroll-Byte / Command zum Auslesen schickt. Bis der Puffer vollstaendig gelesen wurde.

Was nicht gut geht ist, immer nur 1 Byte lesen, dann diese Bytes vom Puffer lesen, dann wieder 1 USART Byte lesen, etc.  Denn um mit dem CPC zu kommunizieren, muss der USART abgeschaltet werden, und die Kommunikation mit dem CPC kostet dann zu viel Zeit, sodass man Bytes verpassen wuerde. Wenn aslo lange USART Nachrichten zu empfangen sind, muss dass die LS Firmware autark und ohne CPC-Zutun (und ohne Unterbrechungsmoeglichkeiten) tun. Daher also <n> Bytes am Stueck lesen, oder bis zu einem Ende-Token.

Noch andere Ideen?

Schreiben auf das USART ist natuerlich trivial - erst alle Nutzbytes senden, dann Controll Byte / Kommando zum senden des Puffers ueber USART.


LambdaMikel

Hier ist uebrigens das Teil das man braucht wenn man echtes DB9 aus dem TTL USART benoetigt:

https://www.amazon.com/gp/product/B07GP9SLCH/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1


Habe mir mal 2 bestellt. Dann kann sich LambdaSpeak endlich mit meinen DECtalk unterhalten   :smiley027:

TFM

Also was wäre mir persönlich wichtig?

- I/O Kompatibilität zum USIfAC bzw. CPC-Booster(+) bzw. irgendetwas anderem seriellem
- Abfrage-Möglichkeit, ob dieses neue LS3 Serielle da ist oder nicht
- Puffer für Bytes im LS3
- Diverse Datenraten
- Datensicherheit, wenn möglich kein "Rauschen" wie bei anderen Produkten

Zum schreiben:
Man schickt die Zeichen einfach. Dazu eventuell noch eine Möglichkeit um abzufragen, wie viele ich schicken kann (falls die Datenrate langsam ist und der CPC schneller als der LS3)

Zum lesen:
Funktion um abzufragen wie viele Bytes im Empfangspuffer sind (also gelesen werden können). Und natürlich Byte lesen.

Es wäre auch cool wenn man Funktionen hätte um z.B. 128/256/??? Bytes zu senden und empfangen. Also im Block, das würde alles schneller machen.

TFM of FutureSoft
http://www.futureos.de --> Das Betriebssystem FutureOS (Update: 24.12.2025)
http://futureos.cpc-live.com/files/LambdaSpeak_RSX_by_TFM.zip --> RSX ROM für LambdaSpeak (Update: 29.01.2025)

LambdaMikel

Quote from: TFM on 08. April 2019, 20:46:37
Also was wäre mir persönlich wichtig?

- I/O Kompatibilität zum USIfAC bzw. CPC-Booster(+) bzw. irgendetwas anderem seriellem

Eher nicht machbar. USIfAC funktioniert anders, und ich habe nur einen CPC Port...

Quote
- Abfrage-Möglichkeit, ob dieses neue LS3 Serielle da ist oder nicht

Mittels Verionsnummer?

Quote
- Puffer für Bytes im LS3

Genau, so ist es gemacht. Gepuffert fuers Schreiben und fuers Lesen. Byte *direkt rausschreiben* (ungepuffert) kann ich auch machen, ist aber langsamer...

Quote
- Diverse Datenratn
- Datensicherheit, wenn möglich kein "Rauschen" wie bei anderen Produkten

So ist es.

Quote
Zum schreiben:
Man schickt die Zeichen einfach. Dazu eventuell noch eine Möglichkeit um abzufragen, wie viele ich schicken kann (falls die Datenrate langsam ist und der CPC schneller als der LS3)

Wie gesagt, momentan ist gepuffert. Puffer vollschreiben, dann Senden Kontroll-Byte senden. Ab geht die Post an den USART.

Ich kann allerdings auch noch einen *senden einzelnes empfangenes CPC Byte sofort* implementieren.

Puffer-Ueberlauf-Schutz brauchen wir glaube ich nicht. Jedes Byte wird in diesem Modus sofort rausgeschrieben. Und zur Not kann ich den CPC jederzeit anhalten.

Quote
Zum lesen:
Funktion um abzufragen wie viele Bytes im Empfangspuffer sind (also gelesen werden können). Und natürlich Byte lesen.

So ist es.

Quote
Es wäre auch cool wenn man Funktionen hätte um z.B. 128/256/??? Bytes zu senden und empfangen. Also im Block, das würde alles schneller machen.

Genau, haben wir.

LambdaMikel

#262
Weisst Du evtl. wie gross der Buffer im USIFAC ist?

EDIT - hab's gefunden - 920 bytes.

TFM

Genau! Hier kurz das Handbuch dazu...
TFM of FutureSoft
http://www.futureos.de --> Das Betriebssystem FutureOS (Update: 24.12.2025)
http://futureos.cpc-live.com/files/LambdaSpeak_RSX_by_TFM.zip --> RSX ROM für LambdaSpeak (Update: 29.01.2025)

TFM

Nur eines noch... also persönlich finde ich es doof wenn externe Hardware den CPC auf WAIT setzt und damit anhält. Egal ob CPC-Booster oder USIfAC. Es nervt tierisch! Und für BS wie SymbOS nervt es vermutlich noch viel mehr. Da ist mir Hardware lieber, die ich abfragen kann ob ich als Programm was tun muss, anstatt das mir so ein Ding das ganze System ausbremst. (Damit kann man Multitasking (fast) vergessen und jegliche Synchronisation mit dem Bildaufbau ist auch dahin). Das alles kann man sicher sehen wie man will, aber als Programmierer sehe ich es hald so, als Hardware-Macher mag man es diametral anders sehen. Meine Meinung (es ist ja nur eine einzige) soll auch niemandem auf die Füße treten, aber ich wollte es mal loswerden und fühle mich jetzt schon entspannter.

Für den LS3 würde ich mir einfach etwas wünschen das zuverlässig funktioniert. Programmieren kann man es dann schon.  :smiley027:
TFM of FutureSoft
http://www.futureos.de --> Das Betriebssystem FutureOS (Update: 24.12.2025)
http://futureos.cpc-live.com/files/LambdaSpeak_RSX_by_TFM.zip --> RSX ROM für LambdaSpeak (Update: 29.01.2025)

LambdaMikel

#265
LambdaSpeak 3 serial interface ist jetzt fertig. Wait wird nur minimalsbenutzt, um ein neues Byte vom CPC Datenbus zu lesen wenn es ankommt, um sicherzustellen dass die Synchronisation klappt - aber das ist im Microsekunden Bereich (und LS 30 hat das schon immer gemacht).  Ich denke, ich bräuchte das eigentlich gar nicht, aber sicher ist sicher. Wenn Du es bisher nicht negativ bemerkt hast, wirst Du es auch im seriellen Modus nicht merken, da der Mechanismus schon vorher verwendet wurde fürs Datenbyte-Lesen ("Latchen") vom CPC. M.aW., sobal IOREQ WRITE an &FBEE erscheint, wird der CPC kurz angehalten, dann wir das Datenbyte vom Bus gelesen, und dann wird fortgesetzt. Das ist nur, um "Glitches" und "verpasste Bytes" zu verhindern.

Hier ist eine Demo in BASIC - serial Terminal. Funktioniert mit Emic 2 in beide Richtungen (Senden um es zum Sprechen zu bringen, und Query Commands wie "I" geben die aktuellen Settings zurück - ich kann heute Abend mal ein Video schicken, allerdings warte ich damit lieber, bis ich den PC und den NC100 per Kabel ueber LS30 mit dem CPC verbunden habe).

Also, Interface ist ganz einfach:
- LS 30 in den serial mode versetzen: out &fbee,&f1
- dann laeuft der LS in einer "serial mode listener loop", in der man USART senden und empfangen kann. S. screenshots fuer Illustration.

"out &fbee,255" und dann "out &fbee,<val>" sendet  serial command control byte "<val>". Um 255 selbst in den Puffer zu schreiben füer den USART, muss man natürlich  "out &fbee,255" und dann nochmal "out &fbee,255" schreiben. Alle anderen Nutzbytes <> 255 kann man natürlich direkt schreiben, "out &fbee,<val>" für <val> < 255.

Anbei die Listener Loop - ist etwas unschön, da ich 2 existierende Buffer "wiederverwenden" muss (SRAM-Platzmangel!), aber funktioniert:


void usart_on0(uint8_t rate, uint8_t width, uint8_t parity, uint8_t stop_bits) {

  SERIAL_BAUDRATE = rate;
  SERIAL_WIDTH = width;
  SERIAL_PARITY = parity;
  SERIAL_STOP_BITS = stop_bits;

  UBRR0H = 0;   
  switch (rate) {
  case 0 : UBRR0H = ( 520 >> 8) & 0xFF; UBRR0L = 520 & 0xFF; SERIAL_RATE = 2400; break; // 2400
  case 1 : UBRR0H = ( 259 >> 8) & 0xFF; UBRR0L = 259 & 0xFF; SERIAL_RATE = 4800; break; // 4800
  case 2 : UBRR0L = 129; SERIAL_RATE = 9600; break; // 9600
  case 3 : UBRR0L = 86; SERIAL_RATE = 14400; break;  // 14400
  case 4 : UBRR0L = 64; SERIAL_RATE = 19200; break;  // 19200
  case 5 : UBRR0L = 42; SERIAL_RATE = 28800; break;  // 28800
  case 6 : UBRR0L = 32; SERIAL_RATE = 38400; break;  // 38400
  case 7 : UBRR0L = 21; SERIAL_RATE = 57600; break;  // 57600
  case 8 : UBRR0L = 15; SERIAL_RATE = 76800; break;  // 76800
  case 9 : UBRR0L = 10; SERIAL_RATE = 115200; break;  // 115200
  case 10 : UBRR0L = 4; SERIAL_RATE = 250000; break;  // 250000

  default :  UBRR0L = 129; SERIAL_RATE = 9600; // 9600
  }

  UCSR0C = 0;

  switch (parity) {
  case 0 :                                         break; // no parity
  case 1 : UCSR0C |= (1 << UPM01) | (1 << UPM00) ; break; // odd parity
  case 2 : UCSR0C |= (1 << UPM01)                ; break; // even parity
  default : break;
  }

  switch (stop_bits) {
  case 2 :                         break; // 1 stop bit
  case 1 : UCSR0C |= (1 << USBS0); break; // 2 stop bit
  default : break;
  }


  switch (width) {
  case 8 : UCSR0C |= (1 << UCSZ00) | (1 << UCSZ01); break; // 8bit
  case 7 : UCSR0C |=                 (1 << UCSZ01); break; // 7bit
  case 6 : UCSR0C |= (1 << UCSZ00)                ; break; // 6bit
  case 5 :                                          break; // 5bit

  default : UCSR0C |= (1 << UCSZ00) | (1 << UCSZ01);       // 8bit 

  }

  UCSR0B = (1 << TXEN0) | (1 << RXEN0) | (1 << RXCIE0); 

}


//
//
//


void usart_mode_loop() {

  cli();

  LEDS_ON;

  speech_native_busy; 
  command_confirm("Serial mode. Serial commands start with 255.");
  speech_native_ready; 

  z80_run;
 
  usart_on();
  SERIAL_ON;

  uint8_t lo_byte = 0;
  uint8_t hi_byte = 0;

  uint8_t direct_mode = 0; 

  while (1) {

    READ_ARGUMENT_FROM_DATABUS(databus);
   
    if (databus == 255) {

      // command sent!
      // receive command byte - what to do?

      READ_ARGUMENT_FROM_DATABUS(databus);

      if (databus == 255) {

// escape: 255 255 -> 255 !

if (direct_mode) {
  USART_Transmit(databus);
} else {

  if (from_cpc_input_buffer_index < SEND_BUFFER_SIZE) {
    send_msg[ from_cpc_input_buffer_index++ ] = databus;
  } else if ( (from_cpc_input_buffer_index - SEND_BUFFER_SIZE) < SPEECH_BUFFER_SIZE) {
    buffer[ from_cpc_input_buffer_index++  - SEND_BUFFER_SIZE] = databus;
  }

}

break;

      } else {

// dispatch, decode command byte
switch (databus) {

case 1 :  // write USART single byte

  READ_ARGUMENT_FROM_DATABUS(databus);
  USART_Transmit(databus);

  break;

case 2 :  // print buffer to serial

  USART_sendBuffer(from_cpc_input_buffer_index);
  from_cpc_input_buffer_index = 0;

  break;
 
case 3 : // ask for low byte number of bytes in USART input buffer

  SEND_TO_CPC_DATABUS(usart_input_buffer_index & 0xFF);

  break;

case 4 : // ask for high byte number of bytes in USART input buffer

  SEND_TO_CPC_DATABUS( usart_input_buffer_index >> 8);

  break;

case 5 : // ask if buffer is full

  SEND_TO_CPC_DATABUS(usart_input_buffer_index == (SPEECH_BUFFER_SIZE + SEND_BUFFER_SIZE));

  break;

case 6 : // flush receive buffer

  usart_input_buffer_index = 0;
  cpc_read_cursor = 0;

  break;
 
case 7 : // check if byte available

  SEND_TO_CPC_DATABUS( cpc_read_cursor < usart_input_buffer_index  );

  break;

case 8 : // get byte for CPC at current USART input buffer position

  if (cpc_read_cursor >= 0 && cpc_read_cursor < usart_input_buffer_index ) {

    uint8_t data = 0;
   
    if ( cpc_read_cursor < SEND_BUFFER_SIZE) {
      data = send_msg[ cpc_read_cursor ];
    } else if ( (cpc_read_cursor - SEND_BUFFER_SIZE) < SPEECH_BUFFER_SIZE) {
      data = buffer[ from_cpc_input_buffer_index  - SEND_BUFFER_SIZE];
    }

    SEND_TO_CPC_DATABUS( data);
   
  }

case 9 : // get next byte for CPC in USART input buffer

  if (cpc_read_cursor >= 0 && cpc_read_cursor < usart_input_buffer_index ) {

    uint8_t data = 0;
   
    if ( cpc_read_cursor < SEND_BUFFER_SIZE) {
      data = send_msg[ cpc_read_cursor++ ];
    } else if ( (cpc_read_cursor - SEND_BUFFER_SIZE) < SPEECH_BUFFER_SIZE) {
      data = buffer[ from_cpc_input_buffer_index++  - SEND_BUFFER_SIZE];
    }

    SEND_TO_CPC_DATABUS( data);
   
  }

  break;

case 10 : // get previous byte for CPC in USART input buffer
 
  if (cpc_read_cursor >= 0  && cpc_read_cursor < usart_input_buffer_index ) {

    uint8_t data = 0;
   
    if ( cpc_read_cursor < SEND_BUFFER_SIZE) {
      data = send_msg[ cpc_read_cursor-- ];
    } else if ( (cpc_read_cursor - SEND_BUFFER_SIZE) < SPEECH_BUFFER_SIZE) {
      data = buffer[ from_cpc_input_buffer_index--  - SEND_BUFFER_SIZE];
    }

    SEND_TO_CPC_DATABUS( data);
   
  }

  break;

case 11 : // set cursor to given byte position

  READ_ARGUMENT_FROM_DATABUS(lo_byte);
  READ_ARGUMENT_FROM_DATABUS(hi_byte);
 
  cpc_read_cursor = lo_byte + (hi_byte << 8);
   
  break;

case 12 : // reset CPC cursor

  cpc_read_cursor = 0;
 
  break;

case 13 : // set CPC cursor to last byte

  if (usart_input_buffer_index > 0) {
    cpc_read_cursor =  usart_input_buffer_index-1;
  }
 
  break;

case 14 :  // check status

  SEND_TO_CPC_DATABUS(direct_mode);
  break;

case 15 : // announce mode!
 
  LAMBDA_EPSON_ON;      
  sprintf(command_string, "Serial interface active at %lu bauds, %d bits, %d stop bits, and %s parity. %s mode.",
  SERIAL_RATE, SERIAL_WIDTH, SERIAL_STOP_BITS,
  ( SERIAL_PARITY == 1 ? "odd" : ( SERIAL_PARITY == 2 ? "even" : "no" )),
  (direct_mode == 1 ? "direct" : "buffered" ));

  command_confirm(command_string);
 
  usart_input_buffer_index = 0;
  cpc_read_cursor = 0;

  break;

case 16 :  // turn on databus direct printing

  direct_mode = 1; 
  break;

case 17 :  // turn off databus direct printing  -> print to buffer!

  from_cpc_input_buffer_index = 0;
  direct_mode = 0;
  break;

case 20 :
 
  usart_off();  
  LAMBDA_EPSON_ON;      
  speech_native_busy; 
  BLOCKING = 1;
  command_confirm("Quitting serial mode.");
  process_reset();

  return;
  break; 

case 30 : // set BAUDRATE
 
  READ_ARGUMENT_FROM_DATABUS(SERIAL_BAUDRATE);
  usart_off();
  usart_on();

  break;

case 31 : // set WIDTH
 
  READ_ARGUMENT_FROM_DATABUS(SERIAL_WIDTH);
  usart_off();
  usart_on();

  break;

case 32 : // set PARITY
 
  READ_ARGUMENT_FROM_DATABUS(SERIAL_PARITY);
  usart_off();
  usart_on();

  break;

case 33 : // set STOP_BITS
 
  READ_ARGUMENT_FROM_DATABUS(SERIAL_STOP_BITS);
  usart_off();
  usart_on();

  break;

}
      }

    } else {

      // not a control byte, send or buffer:

      if (direct_mode) {

USART_Transmit(databus);

      } else

if (from_cpc_input_buffer_index < SEND_BUFFER_SIZE) {
  send_msg[ from_cpc_input_buffer_index++ ] = databus;
} else if ( (from_cpc_input_buffer_index - SEND_BUFFER_SIZE) < SPEECH_BUFFER_SIZE) {
  buffer[ from_cpc_input_buffer_index++  - SEND_BUFFER_SIZE] = databus;
}   
    }   
  }
}




LambdaMikel

#266
Quote from: TFM on 10. April 2019, 15:27:59
Da ist mir Hardware lieber, die ich abfragen kann ob ich als Programm was tun muss, anstatt das mir so ein Ding das ganze System ausbremst.
...
Für den LS3 würde ich mir einfach etwas wünschen das zuverlässig funktioniert. Programmieren kann man es dann schon.  :smiley027:

Hoffentlich ist das der Fall - es gibt keinen Modus, in dem LS serial den CPC anhält, um Bytes zum USART zu lesen oder zu schreiben. RX USART lesen geht "automatisch" die ganze Zeit, über einen Interrupt ISR handler im LS 30, der empfangene RX USART Bytes in einen Puffer schreibt. Dann kann man den Puffer vom CPC aus abfragen, ob er Bytes enthält etc., und man kann mitteles eines "Read Cursors" vom CPC aus durch den Puffer navigieren und Bytes davon auslesen. Cursor vor, zurück, Cursor-Position setzen, Cursor ans Ende des Puffers, an den Anfang, Puffer löschen, etc.

S. auch Erläuterungen oben bzgl. Datenbus Byte "latchen".

Neue LS300.DSK anbei, mit serial.bas Programm.

Ich denke, es sollte auch mit laengeren Kabeln gut funktionieren, da die Serial TX0/RX0 port vom ATmega durch den CPLD geschleift werden, und das resultiert in Signal-Verstaerkung/ Auffrischung / Verbesserung.

Ich teste demnaechst mal 115 k BAUD und mehr.

TFM

TFM of FutureSoft
http://www.futureos.de --> Das Betriebssystem FutureOS (Update: 24.12.2025)
http://futureos.cpc-live.com/files/LambdaSpeak_RSX_by_TFM.zip --> RSX ROM für LambdaSpeak (Update: 29.01.2025)

LambdaMikel

Quote from: TFM on 12. April 2019, 05:27:12
Wir immer besser!  :smiley027:

Dankeschön! Und auch noch gleich einen Firmware-Fehler gefunden - ein break; war zuviel im Kontroll-Byte dispatcher.
255 255 wurde nicht korrekt nach 255 abgebildet (255 muss mittlels 255 "escaped" werden, da 255 normalerweise Kontroll-Byte signalisiert!)

Gut, dass ich den MP3-Player doch noch mal ausprobiert habe, der benötigt nämlich USART-Befehlssequenzen die 255 enthalten - und ich hatte mich schon gewundert, warum es nicht klappte! Manchmal ist es doch was ganz triviales in der Software, wie ein ; an der falschen Stelle, oder ein break zu viel - wie hier.

Jetzt klappt es:

[CPCEmulator]https://youtu.be/NtUVlTJrOkU[/CPCEmulator]

Sicherlich ein guter Kauf für 4 $ das Module  :smiley027:


LambdaMikel

#269
Und ein letzter Test für heute:

[CPCEmulator]https://youtu.be/uKeZEkyIqtg[/CPCEmulator]

Ich verwende den RS232 level converter mit MAX3232 der inzwischen eingetroffen war:

https://www.amazon.com/gp/product/B07GP9SLCH/ref=ppx_yo_dt_b_asin_title_o02_s00?ie=UTF8&p;sc=1

Neue DSK anbei; diesesmal mit MP3.bas und auch SERIAL.BAS wurde überarbeitet.