L'accès à une carte SD peut atteindre environ 6 Ko/s quand la liaison SPI est assurée par le processeur 6809 d'un ordinateur Thomson. L'objectif de ce projet est d'atteindre un débit dix fois plus élevé.
Auteur : Daniel Coulom - Site internet : Emulateur DCMOTO - Dernière mise à jour le 26 mai 2020
ATTENTION :
Le streaming à 58824 octets par seconde a été amélioré et atteint maintenant 250000 octets par seconde.
Il est conseillé d'utiliser la nouvelle version :
SDSTREAM
Le moyen de décharger le processeur 6809 de la génération de l'horloge pour la liaison SPI est l'utilisation d'un Arduino pour lire la carte SD. L'ordinateur Thomson gère la liaison avec l'Arduino pour récupérer les échantillons de son sur 6 bits, et les joue avec le convertisseur numérique-analogique intégré à l'ordinateur (ou à l'extension musique et jeux).
La transmission est assurée par les deux ports joysticks, permettant une liaison parallèle sur 8 bits avec le port D de l'Arduino (bits D0 à D7). Le signal de contrôle permettant à l'ordinateur Thomson d'assurer le bon débit est la ligne du bouton d'action de la manette 0, utilisée dans ce cas en sortie numérique vers l'entrée D8 de l'Arduino.
Le modèle d'Arduino utilisé est ici un Mini Pro, le moins cher de la gamme équipée du processeur ATmega328P. Les autres modèles, en particulier Nano et Uno, conviennent aussi très bien. Il suffit d'adapter le schéma de câblage à la disposition des entrées-sorties.
L'interface avec la carte micro SD est un module Catalex, le même que celui des interfaces SDMOTO et SDMO. Tout autre modèle compatible avec l'Arduino convient également. Il est connecté à l'Arduino en mode SPI (entrées/sorties numériques D10 à D13).
La photo montre le montage terminé. Les composants nécessaires sont listés ci-dessous. Les prix sont donnés à titre indicatif, sans aucune garantie. Ils ont été relevé sur un site d'enchères le 9 juin 2015, avec l'option monde entier, en achat immediat port gratuit. On trouve moins cher en utilisant la version américaine du même site d'enchères.
- Arduino Mini Pro en kit : 1,76 € - 10 DB9 femelles a souder : 1,28 € - Module micro SD Catalex : 1,11 € - 40 fils Dupont Fem-Fem. : 1,04 € Total : 5,19 € Pour programmer l'Arduino Mini Pro il faut ajouter l'interface USB : - Convertisseur USB CH340 : 1,48 €
Version sans soudure :
Les connecteurs DB9 peuvent être des modèles à souder (à droite sur la photo), ou des modèles à picots droits pour circuit imprimé (à gauche), sur lesquels on peut connecter les fils Dupont femelles sans soudure. Notez que les coquilles métalliques des connecteurs de gauche n'ont pas été retirées. C'est acceptable pour la plupart des ordinateurs Thomson, sauf le TO8D. Les connecteurs manettes du TO8D sont en retrait par rapport au boîtier, il faut retirer les coquilles métallique des fiches DB9, comme à droite de la photo, en perçant les deux rivets.
La version sans soudure nécessite donc l'utilisation de connecteurs DB9 à picots droits (plus chers) et d'un Arduino Mini Pro avec les connecteurs déjà soudés (plus cher), ce qui double le prix du montage.
Ci-dessous les connecteurs DB9F à souder et à picots droits, les fils Dupont femelle-femelle, l'Arduino Mini Pro en kit, le convertisseur USB à base de CH340 et le module Catalex pour carte micro SD.
La bibliothèque standard de l'Arduino pour accéder à la carte SD est trop lente pour atteindre des débits élevés. A la place j'utilise les modules sd_l0, sd_l1 et sd_l2 de la bibliothèque SimpleSDAudio
Ils sont utilisés pour rechercher le fichier à jouer dans le répertoire de la carte SD (dans l'exemple ce fichier est ccr.sd). On obtient l'adresse physique du début du fichier. Ensuite, pour des raisons de performances, la carte est lue séquentiellement avec la commande CMD18 (lecture multiblocs). Cette méthode est la plus rapide, mais nécessite que le fichier ne soit pas fragmenté. Chaque octet est transmis à la demande de l'ordinateur Thomson, quand le signal de contrôle passe à l'état bas.
/**************************************************\ * S D P L A Y 5 8 * * (c) 2015 - Daniel Coulom * * http://dcmoto.free.fr/ * * http://forum.system-cfg.com/ * *--------------------------------------------------* * Ce code est distribue gratuitement dans l'espoir * * qu'il sera utile, mais sans aucune garantie et * * sans engager la responsabilité de l'auteur. * * Vous pouvez l' utiliser, le modifier et le * * diffuser librement, en conservant cette licence * * et les références de l'auteur dans toutes les * * copies. L'exploitation commerciale est interdite.* \**************************************************/ /*************************************************** * Version 2015.06.03 * **************************************************** Historique 2015.06.03 optimisation du code 2015.06.02 desactivation des interruptions 2015.05.23 n'utilise plus SimpleSDAudio.cpp 2015.05.19 premiere version operationnelle Communication parallele avec un ordinateur Thomson Lecture des donnees dans un fichier sur carte SD Envoi des octets sur le port D a destination du port manettes de l'ordinateur Thomson. Connexion module Catalex pour carte micro SD GND --> GND SCK --> D13 MISO --> D12 MOSI --> D11 VCC --> VCC (5V) CS --> D10 Connexion DB9 de la manette 0 1 --> D0 (RX) 2 --> D1 (TX) 3 --> D2 4 --> D3 5 --> VCC (+5V) 6 --> D8 7 --> non connecte 8 --> non connecte 9 --> GND Connexion DB9 de la manette 1 1 --> D4 2 --> D5 3 --> D6 4 --> D7 5 --> non connecte 6 --> non connecte 7 --> non connecte 8 --> non connecte 9 --> non connecte This sketch uses the SimpleSDAudio library for SD card access. Visit SimpleSDAudio website for more information: http://www.hackerspace-ffm.de/wiki/index.php?title=SimpleSDAudio */ #include#include #include #define SD_FILE "ccr58.sd" uint8_t SD_L1_CardCommand(uint8_t cmd, uint32_t arg); SD_L2_File_t AudioFileInfo; uint8_t string[1024]; void setup() { int i; // compteur de boucle int index; //index dans le buffer int wait0xfe; // indicateur d'attente octet 0xfe //desactiver les interruptions noInterrupts(); // Configure pin8 as an input (thomson request) pinMode(8, INPUT); // Configure port D as an output PORTD = 0x00; DDRD = 0xff; // Initialize SD card SD_L0_CSPin = 10; SD_L2_Init(string); SD_L0_SpiSetHighSpeed(); // Search for file SD_FILE in Rootdir (=cluster 0), // search shortname files only (0x00,0x18) SD_L2_SearchFile((uint8_t *)SD_FILE, 0UL, 0x00, 0x18, &AudioFileInfo); // send CMD18 (multiblock read) uint32_t offset = AudioFileInfo.ActSector; // offset = secteur if (SD_L1_GetCardType() != SD_CARD_TYPE_SDHC) // si carte non SDHC offset <<= 9; // offset = octet SD_L1_CardCommand(18, offset); // lance CMD18 while(SD_L0_SpiRecvByte() != 0xfe); // attente octet $FE de debut de bloc uint32_t count = 0; // compteur d'echantillons while(count < AudioFileInfo.Size) // tant qu'il reste des echantillons { // remplir le buffer avec deux octets a chaque boucle // (512 octets de donnees et 2 octets de CRC) // et envoyer un seul octet par boucle sur le port D index = 0; for(i = 0; i < 257; i++) // boucle 257 fois { string[index++] = SD_L0_SpiRecvByte(); // octet lu sur la carte while(digitalRead(8) == LOW); // wait Thomson acknowledge string[index++] = SD_L0_SpiRecvByte(); // octet lu sur la carte PORTD = string[i]; // write byte to output port while(digitalRead(8) == HIGH); // wait Thomson request } // envoyer les octets suivants (lus dans le buffer) // tout en attendant l'octet 0xfe wait0xfe = 1; for(i = 257; i < 512; i++) { while(digitalRead(8) == LOW); // wait Thomson acknowledge if(wait0xfe) if(SD_L0_SpiRecvByte() == 0xfe) // lire un octet, tester 0xfe wait0xfe = 0; // raz flag d'attente 0xfe PORTD = string[i]; // write byte to output port while(digitalRead(8) == HIGH); // wait Thomson request } count += 512; // 512 echantillons par boucle } } void loop(void) { }
L'initialisation consiste à masquer les interruptions et à configurer le port B du PIA6821 "musique et jeux" en sortie pour les bits 0 à 5 (entrée du convertisseur numérique-analogique), et en entrée pour le bit 6 (signal de contrôle).
La boucle de lecture envoie le signal "request to send" (bit 6 à zéro), lit un octet, le joue, remet le bit 6 à un en prévision de la prochaine transmission. Cette boucle comporte 17 cycles et joue donc 58824 échantillons par seconde.
/**************************************************\ * S D P L A Y 5 8 * * (c) 2015 - Daniel Coulom * * http://dcmoto.free.fr/ * * http://forum.system-cfg.com/ * *--------------------------------------------------* * Ce code est distribue gratuitement dans l'espoir * * qu'il sera utile, mais sans aucune garantie et * * sans engager la responsabilité de l'auteur. * * Vous pouvez l' utiliser, le modifier et le * * diffuser librement, en conservant cette licence * * et les références de l'auteur dans toutes les * * copies. L'exploitation commerciale est interdite.* \**************************************************/ * Communication parallele 8 bits avec un Arduino * Lecture des octets par le port manette * Joue les echantillons 6 bits a 58824 Hz /**************************************************\ * Version 2015.06.03 * \**************************************************/ * Historique * 2015.06.03 retour au Basic en fin de morceau * 2015.06.03 compatibilite MO et TO * 2015.05.23 ajout de l'initialisation du PIA 6821 * 2015.05.19 suppression temporisation * 2015.05.11 suppression du test arduino ready * 2015.05.10 debut du projet *------------------------------------------------------ * INITIALISATIONS *------------------------------------------------------ ORG $9000 PSHS U,Y,X,DP,B,A,CC empile les registres ORCC #$D0 masque les interruptions LDA #$E7 valeur initialisation DP pour TO LDX #$1F40 adresse pour test RAM ou ROM LDB ,X lecture adresse X COM ,X tente de modifier adresse X CMPB ,X test modification adresse X BEQ INIT1 pas de difference -> TO COM ,X retablissement adresse X LDA #$A7 valeur initialisation DP pour MO INIT1 TFR A,DP initialisation DP CLRA A=$00 CLRB B=$00 STD <$CE selectionne DDRA et DDRB LDB #$7F B=$7F STD <$CC PA b0-7 en entree, PB b0-7 en sortie ORA #$04 set b2 STA <$CE selectionne PORTA STA <$CF selectionne PORTB *------------------------------------------------------ * LECTURE SEQUENTIELLE * 17 cycles = 58824 Hz *------------------------------------------------------ LECT0 ANDA #$3F (2) clear bit 6 STA <$CD (4) request to send LDA <$CC (4) lecture octet avec b6=1 STA <$CD (4) acknowledge BPL LECT0 (3) nouvelle lecture *------------------------------------------------------ * RETOUR AU BASIC *------------------------------------------------------ PULS CC,A,B,DP,X,Y,U,PC retour au Basic END
Pour obtenir une bonne qualité, il faut partir d'un enregitrement à plus de 58800 échantillons par seconde. Dans l'exemple c'est un fichier .wav remasterisé à 88200 échantillons par seconde. Avec CoolEdit2000 ou tout autre logiciel de traitement audio, on le transforme en mono 8 bits à 58824 échantillons par seconde. Pour le passer en 6 bits, il faut ensuite l'amplifier de 25%, puis le décaler pour que les échantillons soient dans la plage 64-127. Avec CoolEdit2000 c'est le paramètre "DC Bias adjust -25%". Il vaut mieux l'enregistrer au format .raw, de préférence au format .wav qui produirait quelques parasites lors de la lecture de l'en-tête. Vous pouvez aussi utiliser le fichier ayant servi au développement de ce projet : ccr58.zip
Le programme Basic suivant permet de jouer la musique sur un ordinateur MO ou TO. Le programme s'arrête en fin de fichier. Pour jouer à nouveau il suffit de réinitialiser l'Arduino en appuyant sur le bouton RESET et de relancer le programme Basic.
1 '================================ 2' SDPLAY58.BAS 3 '================================ 10 A=&H9000 20 READX$:IFX$="**"THEN90 30 POKEA,VAL("&H"+X$):A=A+1:GOTO20 90 EXEC&H9000:END 100 DATA 34,7F,1A,D0,86,E7,8E,1F 101 DATA 40,E6,84,63,84,E1,84,27 102 DATA 04,63,84,86,A7,1F,8B,4F 103 DATA 5F,DD,CE,C6,7F,DD,CC,8A 104 DATA 04,97,CE,97,CF,84,3F,97 105 DATA CD,96,CC,97,CD,2A,F6,35 106 DATA FF,**
La qualité du son produit est exceptionnelle pour un ordinateur 8 bits. Je vous conseille vivement de réaliser ce petit montage pour juger vous-même du résultat obtenu.
Ci-dessous la photographie du premier prototype opérationnel et le montage définitif en fonctionnement.
Grâce au débit de transmission élevé, le même montage a aussi été utilisé pour de la vidéo avec son. Rechercher à la section Programmes du site dcmoto les démonstrations SDANIM3 Cat & Mouse et SDANIM3 Brassens.
La source principale d'informations sur ce projet de streaming avec un Arduino est le forum system-cfg :
Vous pouvez y relire toute la genèse et demander de l'aide en cas de difficulté.
© 2017 - Daniel Coulom
contacter l'auteur