SDLEP-READER remplace tous les magnétophones d'ordinateurs.

Placez ici vos trucs et astuces, étalez sans retenue votre savoir-faire et votre science qui va nous permettre de redonner une apparence neuve et fonctionnelle à nos bouzes.

Modérateurs : Carl, Papy.G, fneck

Daniel
Messages : 10261
Enregistré le : 01 mai 2007 18:30
Localisation : Vaucluse
Contact :

Re: SDLEP-READER remplace tous les magnétophones d'ordinateurs.

Message par Daniel » 05 mars 2018 14:11

@Voyageur : Merci pour ce retour d'information. Faire un article sur SDLEP-READER est une bonne idée pour faire connaître ce système.

Quant à vouloir développer avec un Arduino un périphérique capable d'enregistrer la sortie de l'ordinateur dans un fichier .lep, j'ai exactement les mêmes arguments que hlide pour dire que c'est extrêmement difficile. J'en ajoute un autre : il n'est pas sûr que l'Arduino soit assez rapide pour lire le signal, le coder au format .lep et l'écrire sur la carte SD en temps réel.

Au départ, SDLEP-READER a été développé pour Thomson dans le but de lire les programmes sur cassette n'ayant pas encore été convertis en disquette. Avec les ordinateurs Thomson l'écriture d'une cassette n'a aucun intérêt, il est beaucoup plus simple et cent fois plus rapide d'écrire dans une image de disquette sur carte SD, ou même dans une "vraie" disquette.

Pour d'autres ordinateurs ne disposant pas de disquette ni de carte SD, je conçois bien que l'écriture d'une cassette soit nécessaire. Je souhaite bon courage au développeur qui voudra se lancer dans le projet.
Daniel
L'obstacle augmente mon ardeur.

hlide
Messages : 348
Enregistré le : 29 nov. 2017 10:23

Re: SDLEP-READER remplace tous les magnétophones d'ordinateurs.

Message par hlide » 06 mars 2018 11:53

Pas impossible mais avec des limitations : http://tmrh20.github.io/AAAudio/

- il faut utiliser la libraririe SdFat qui est nettement plus rapide que la librarie Sd standard.
- dans le cas d'un UNO/NANO/MEGA, il peut lire jusqu'à du WAV 24-32 KHz, 8-bit, mono et enregistrer du 11-16 KHz.

Cependant le source utilise par défaut du 16KHz pour du 16MHz.

Ce que j'en pense :
- l'écriture DAC se fait apparemment au travers d'un timer #1 avec un buffer de 128 octets (paramétrable) - on capture donc un sample avec une périodicité précise en libérant des cycles CPU pour faire autre chose en parallèle hors interruption.
- la lecture ADC se fait apparemment au travers d'une DMA avec un buffer de 128 octets (paramétrable) - on émet donc un sample avec une périodicité précise en libérant des cycles CPU pour faire autre chose en parallèle.
- si on converti directement le sample en LEP et non en WAV, on a beaucoup moins d'activité d'écriture dans le SD et donc on est moins sensible au temps passé à écrire un octet dans le SD. En effet, en lisant le sample dans l'interruption, on détermine en fonction d'un seuil si le signal est haut ou bas, et tant que le créneau reste le même à chaque sample, on n'écrit pas l'octet final dans le buffer sauf si le nombre de samples excède ce que l'octet peut encoder. Bref, on reprend l'algorithme de conversion de DCLEP : l'activité DMA fait le travail de remplir le buffer avec des données LEP. En dehors de l'interruption, on vide le buffer dans le SD avec moins de pression que si ça avait été des samples WAV car le nombre d'octet LEP varie en fonction de la periode d'une pulsation. Dans mon cas, une pulsation longue faisait 21 samples à 44,1 KHz. Si on ramène à 16KHz, on aurait besoin de 7-8 samples à 16KHz pour encoder un seul octet LEP représentant une pulsation longue.
- généralement il y a des marquages au début genre GAP/TAPEMARK qui sont souvent une succession de pulsation courte/longue. On pourrait donc déterminer par ce biais les valeurs médianes d'une pulsation courte et d'une pulsation longue pour pouvoir corriger ces périodes et enregister des octets LEP plus propres.
- l'avantage à avoir un DAC ici n'est pas évident puisque l'on peut se contenter d'une sortie tout ou rien comme c'est déjà le cas avec SDLEP-READER. Néanmoins, le fait d'utiliser le timer #1 pour émettre les pulsations avec des périodes précises est tentant. Si effectivement l'interruption se contente de "consommer" l'octet LEP courant de cette manière :

Code : Tout sélectionner

ISR(TIMER1_OVF_vect)
{
	// lep_bit       : définit l'état BAS ou HAUT du créneau de l'octet LEP courant, initialement à HAUT
	// lep_period    : définit la période de la pulsation de l'octet LEP courant, initialement à 1
	// lep_next_data : octet LEP à venir préchargé depuis le SD en dehors de l'interruption

	// fin de période de la pulsation avant inversion d'état pour marquer un front ?		
	if (--lep_period == 0)
	{
		// on se prépare avec l'octet suivant.
		lep_bit    = (lep_next_data < 0) ? false : true;
		lep_period = (lep_bit ? lep_next_data : -lep_next_data) & 127;
		
		// et on informe le code en dehors de l'interruption.
		// qu'il faut charger l'octet suivant dans lep_next_data.
		lep_next_data_needed = true;
		
		// case spécial d'une période à 0.
		if (lep_period == 0)
		{
			// la période de la pulsation précédente se prolonge avec l'octet suivant.
			lep_period = lep_bit ? 127 : -127;
		}
		// cas nominal
		else
		{
			// on change la valeur du pin READ		
			setReadPin(lep_bit);
		}
	}
}
Après l'argument d'utiliser l'interruption timer #1 pour une résolution de 16 µs peut sembler discutable.

Répondre