From cb5b45414b9f639921b58df43e837c44e10d33d2 Mon Sep 17 00:00:00 2001 From: tuxmain Date: Tue, 12 Jul 2022 14:37:05 +0200 Subject: [PATCH] Initial commit --- README.md | 71 +++++++++++++++ teensy_case.scad | 33 +++++++ teensy_case.stl | Bin 0 -> 122484 bytes telephone/telephone.ino | 186 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 290 insertions(+) create mode 100644 README.md create mode 100644 teensy_case.scad create mode 100644 teensy_case.stl create mode 100644 telephone/telephone.ino diff --git a/README.md b/README.md new file mode 100644 index 0000000..85c372e --- /dev/null +++ b/README.md @@ -0,0 +1,71 @@ +# Téléphone jukebox + +Les instructions qui suivent ont été testées avec des Teensy versions 3.1 et 4.0 (et les modules audio correspondant). + +## Électronique + +* Souder le Teensy sur la carte audio. Le plus compact est de les empiler à l'aide de broches. Faites bien attention à les mettre dans le bon sens (les noms des pins doivent correspondre). Il n'est pas nécessaire de connecter les pins 0 à 5. +* Ouvrir le boîtier du téléphone par les deux vis du dessous +* Positionner le boulon de réglage glissant sur "3/MINI" (s'il existe sur votre modèle) +* Relier le GND du Teensy (un trou libellé "G" ou "GND" sur la carte audio) au fil rouge-blanc du cadran (boulon II) +* Relier le fil rouge-blanc du cadran (boulon II) au fil jaune de la prise en T (boulon 15) +* Relier le pin 2 du Teensy au fil blanc de la prise en T (boulon 11) +* Relier le VGND du module audio (pad de la prise jack le plus vers l'extérieur, dans le coin de la carte) au fil bleu du combiné (boulon 3) +* Relier le canal droit ou gauche de la prise jack (un trou libellé L ou R à côté de la prise jack) au fil rouge du combiné (boulon 5) + +Si les fils sont cassants (monobrins), je conseille de les enrouler autour du manchon en métal de la patte qui est fixée au boulon, plutôt que de l'enrouler autour de la vis serrée avec le boulon, afin d'éviter de trop contraindre le fil. + +Attention, GND et VGND ne doivent pas être reliés. + +## Logiciel + +Programmer le Teensy avec le programme fourni. + +## Finition + +* Fabriquer le boîtier d'isolation du Teensy à l'aide d'une imprimante 3D (`teensy_case.stl`), et le placer sur le Teensy (il peut être fixé avec des boulons M3). +* Si besoin, faire un petit trou dans la coque du téléphone pour faire passer le câble USB (ce qui permet l'alimentation et la programmation facilement). +* Indiquer quelque part sur l'appareil les informations nécessaires à son utilisation ou son amélioration futures (par exemple l'adresse de ce dépôt). + +## Utilisation + +### Fichiers audio + +Les fichiers doivent être au format WAV, taux d'échantillonnage (sampling rate) 44100Hz, 16bit. Les noms des fichiers doivent être de `0.wav` à `9.wav`, ce qui correspond aux chiffres du cadran. + +Le son peut être en stéréo, mais un seul des deux canaux sera joué. + +Pour convertir un fichier audio : +* Ouvrir le fichier avec Audacity +* Sélectionner la piste en cliquant dessus +* Menu "Pistes" -> "Rééchantillonner" +* Sélectionner "44100" puis Valider +* Menu "Fichier" -> "Exporter" -> "Exporter en WAV" +* Choisir l'encodage "Signed 16-bit PCM" et enregistrer le fichier. + +La conversion peut également être effectuée en ligne de commande : +```bash +ffmpeg -i FICHIER_EXISTANT -y -ar 44100 -ac 1 -aq 16 CHIFFRE.wav +``` + +### Partitionnement + +Si le Teensy n'arrive pas à lire la carte SD (ce qui est signalé par un bip toutes les 2 secondes), vérifier le partitionnement, qui doit être FAT32 (et non FAT16, par exemple). + +## Améliorations + +Pistes d'amélioration qui n'ont pas encore été réalisées : + +* Les deux sorties L/R pourraient être utilisées pour contrôler deux téléphones. Le Teensy pourrait alors être dans un boîtier externe, relié aux téléphones par leur prise en T (moyennant un recâblage minime à l'intérieur des téléphones). +* Faire sonner la cloche ? +* Numéros à plusieurs chiffres. Cela nécessite la détection de la fin de la numérotation, soit avec un nombre fixé de chiffres, soit avec un timeout, soit avec des règles de numérotation spéciales, éventuellement avec découverte des fichiers sur la carte SD. +* Microcontrôleur moins cher ? (par exemple un ATtiny, mais à voir pour l'audio/SD) +* Interaction avec un ordinateur et une carte son (permet plus de complexité et déleste le microcontrôleur de la gestion du son) + +## Licence + +CopyLeft 2022 Pascal Engélibert + +Ces instructions sont mises à disposition selon les termes de la licence [CC BY-SA 4.0](https://creativecommons.org/licenses/by-sa/4.0/). + +Merci à la compagnie [Léna d'Azy](https://www.lenadazy.fr/) d'avoir financé la conception et la documentation. diff --git a/teensy_case.scad b/teensy_case.scad new file mode 100644 index 0000000..26b804d --- /dev/null +++ b/teensy_case.scad @@ -0,0 +1,33 @@ +// Copyright 2022 Pascal Engélibert +// License CC0 + +module TeensyCase( + bolt_d = 4, // adapted for M3 bolts + bolt_d2 = 7.4, + bolt_h = 5, + l = 39, + w = 39, + th = 2, + bolt1_x = 4.5, + bolt1_y = 4, + bolt2_x = 33.75, + bolt2_y = 4, + bolt3_x = 21, + bolt3_y = 35, +) { + difference() { + union() { + cube([l, w, th]); + translate([bolt1_x, bolt1_y, 0]) cylinder(d=bolt_d2, h=th+bolt_h, $fn=60); + translate([bolt2_x, bolt2_y, 0]) cylinder(d=bolt_d2, h=th+bolt_h, $fn=60); + translate([bolt3_x, bolt3_y, 0]) cylinder(d=bolt_d2, h=th+bolt_h, $fn=60); + } + + translate([bolt1_x, bolt1_y, 0]) cylinder(d=bolt_d, h=th+bolt_h+1, $fn=40); + translate([bolt2_x, bolt2_y, 0]) cylinder(d=bolt_d, h=th+bolt_h+1, $fn=40); + translate([bolt3_x, bolt3_y, 0]) cylinder(d=bolt_d, h=th+bolt_h+1, $fn=40); + } +} + +TeensyCase(bolt_h=9.2); +translate([0, -5, 0]) mirror([0, 1, 0]) TeensyCase(bolt_h=2); diff --git a/teensy_case.stl b/teensy_case.stl new file mode 100644 index 0000000000000000000000000000000000000000..37c1a8957abe1dd7329983535bd4a5cc6c2a88d2 GIT binary patch literal 122484 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 F0{|zHo_zoS literal 0 HcmV?d00001 diff --git a/telephone/telephone.ino b/telephone/telephone.ino new file mode 100644 index 0000000..4e0dff3 --- /dev/null +++ b/telephone/telephone.ino @@ -0,0 +1,186 @@ +/* + * CopyLeft 2022 Pascal Engélibert + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, version 3 of the License. +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. +You should have received a copy of the GNU Affero General Public License along with this program. If not, see https://www.gnu.org/licenses/. + */ + +// Telephone Jukebox +// +// Three types of output may be used, by configuring the code below. +// +// 1: Digital I2S - Normally used with the audio shield: +// http://www.pjrc.com/store/teensy3_audio.html +// +// 2: Digital S/PDIF - Connect pin 22 to a S/PDIF transmitter +// https://www.oshpark.com/shared_projects/KcDBKHta +// +// 3: Analog DAC - Connect the DAC pin to an amplified speaker +// http://www.pjrc.com/teensy/gui/?info=AudioOutputAnalog +// +// To configure the output type, first uncomment one of the three +// output objects. If not using the audio shield, comment out +// the sgtl5000_1 lines in setup(), so it does not wait forever +// trying to configure the SGTL5000 codec chip. +// +// The SD card may connect to different pins, depending on the +// hardware you are using. Uncomment or configure the SD card +// pins to match your hardware. +// +// Two pins can be used (one for hang up detection and one for counting), but it also works well with only one pin for both functions. + +#include +#include +#include +#include +#include + +//#define PIN_PULSE 4 +#define PIN_STOP 2 + +#define PULSE_DELAY 100 + +unsigned long pulses_end = 0; +unsigned int pulses = 0; +bool pulse = false; + +AudioMixer4 mix2; +AudioMixer4 mix1; +AudioSynthWaveform waveform1; +AudioPlaySdWav wav1; +// Use one of these 3 output types: Digital I2S, Digital S/PDIF, or Analog DAC +AudioOutputI2S phone1; +//AudioOutputSPDIF phone1; +//AudioOutputAnalog phone1; +//On Teensy LC, use this for the Teensy Audio Shield: +//AudioOutputI2Sslave phone1; + +AudioConnection c1(waveform1, 0, mix1, 0); +AudioConnection c2(waveform1, 0, mix2, 0); +AudioConnection c3(wav1, 0, mix1, 1); +AudioConnection c4(wav1, 1, mix2, 1); +AudioConnection c5(mix1, 0, phone1, 0); +AudioConnection c6(mix2, 0, phone1, 1); + +AudioControlSGTL5000 sgtl5000_1; + +// Use these with the Teensy Audio Shield +#define SDCARD_CS_PIN 10 +#define SDCARD_MOSI_PIN 7 +#define SDCARD_SCK_PIN 14 + +// Use these with the Teensy 3.5 & 3.6 SD card +//#define SDCARD_CS_PIN BUILTIN_SDCARD +//#define SDCARD_MOSI_PIN 11 // not actually used +//#define SDCARD_SCK_PIN 13 // not actually used + +// Use these for the SD+Wiz820 or other adaptors +//#define SDCARD_CS_PIN 4 +//#define SDCARD_MOSI_PIN 11 +//#define SDCARD_SCK_PIN 13 + +void setup() { + pinMode(PIN_STOP, INPUT_PULLUP); + //pinMode(PIN_PULSE, INPUT_PULLUP); + + AudioMemory(8); + + // Comment these out if not using the audio adaptor board. + // This may wait forever if the SDA & SCL pins lack + // pullup resistors + sgtl5000_1.enable(); + sgtl5000_1.volume(0.5); + + waveform1.begin(WAVEFORM_SINE); + waveform1.frequency(440); + + SPI.setMOSI(SDCARD_MOSI_PIN); + SPI.setSCK(SDCARD_SCK_PIN); + if(!SD.begin(SDCARD_CS_PIN)) { + // Error: Cannot read SD card + while(true) { + if(!digitalRead(PIN_STOP)) { + waveform1.amplitude(0.5); + delay(250); + waveform1.amplitude(0.0); + delay(1750); + } + } + } +} + +void play_track(unsigned int track) { + char filename[16]; + sprintf(filename, "%d.WAV", track); + wav1.play(filename); +} + +void loop() { + /*if(digitalRead(PIN_STOP)) { + waveform1.amplitude(0.0); + if(wav1.isPlaying()) { + wav1.stop(); + } + } else { + if(wav1.isPlaying()) { + waveform1.amplitude(0.0); + } else { + waveform1.amplitude(0.5); + } + } + + if(digitalRead(PIN_PULSE)) { + if(!pulse) { + pulses ++; + pulse = true; + } + } + else if(pulse) { + pulse = false; + pulses_end = millis() + PULSE_DELAY; + } + else if(pulses) { + if(millis() >= pulses_end) { + if(!digitalRead(PIN_STOP)) + play_track(pulses); + pulses = 0; + } + }*/ + + // If phone is hang up + if(digitalRead(PIN_STOP)) { + // Stop tone and music + waveform1.amplitude(0.0); + if(wav1.isPlaying()) { + wav1.stop(); + } + + if(!pulse) { + pulse = true; + pulses ++; + pulses_end = millis() + PULSE_DELAY; + } + else if(millis() > pulses_end) { + pulses = 0; + } + } else { + if(wav1.isPlaying()) { + // Stop tone + waveform1.amplitude(0.0); + } else { + // Start tone + waveform1.amplitude(0.5); + } + + if(pulse) { + pulse = false; + pulses_end = millis() + PULSE_DELAY; + } else if(pulses && millis() > pulses_end) { + play_track(pulses % 10); + pulses = 0; + } + } + + delay(10); +}