English Version French Version Spanish Version

MIDIbox Hardware Platform, Module IIC MIDI 

Le module IIC MIDI procure un pontage entre les interfaces MIDI et IIC, et a été conçu principalement pour les micro-contrôleurs PIC16F88 de Microchip, il fonctionne avec un firmware spécial (et pas sous MIOS!).

IIC et MIDI sont toutes deux des interfaces série:

  • L'interface IIC (Inter-IC, l'abrévation "I2C" est aussi utilisée) a été conçue pour réaliser des échanges de données à des débits élevés entre différentes puces, via simplement deux conducteurs: un signal d'horloge (clock) et un conducteur données (datas)
  • L'interface MIDI (Musical Instrument Digital Interface) est une interface "asynchrone" que vous devez déjà bien connaître (pour preuve, l'intérêt que vous portez à ce site! ;-)

La combinaison de ces deux interfaces ouvre la possibilité d'accéder à plusieurs ports MIDI In et Out à partir d'un seul micro-contrôleur. De plus, les "esclaves" IIC MIDI prennent en charge eux-même quelques tâches de gestion "haut-niveau" du protocole MIDI, ce qui a pour effet de libérer des ressources en termes de temps et de mémoire pour le module CORE "maître". Ceci a pour effet d'améliorer les performances générales.

Le firmware a été dévellopé pour gérer jusqu'à 4 esclaves IIC MIDI  via le bus IIC, avec un module CORE maître:

Chaque esclave a besoin d'une adresse unique, qui doit être sélectionnée à l'aide de deux jumpers (encodage binaire). En théorie, jusqu'à 127 esclaves pourraient être chaînés sur le bus en définissant autant d'adresses dans le firmware, mais en pratique, la charge sur le bus augmenterait a un tel niveau que les buffers seraient en surchage, entraînant la perte de données. Les considérations à propos des performances forment un sujet complexe, et je ne suis pas sûr de trouver un jour le temps d'en expliquer tous les détails ici. Mais je peux déjà dire qu'aucun problème de performance ne devrait survenir en utilisant jusqu'à  4 module IIC_MIDI esclaves - c'est la combinaison que j'utilise pour mon propre MIDI Router, qui sera sérieusement testé en condition réelle dans les années à venir :)

Il faut ajouter ici que le bus IIC peut accueuillir non seulement des modules MBHP_IIC_MIDI mais aussi des BankSticks (EEPROMs IIC), des LCDs IIC ou encore d'autres micro-contrôleurs disposant d'une interface esclaves IIC slave - le firmware MBHP_IIC_MIDI  peut être utiliser comme base pour d'autres "gadgets", comme des sensors spéciaux, des extensions IO analogue/digitale, pont vers les ports RS232, PS2  ou... pourquoi pas une connectique ethernet, une liaison wireless ou un modem? ;-)

Cas d'Utilisation

Le module a été dévellopé pour répondre aux besoins suivant:

  • afin de contourner le bug silicone EUSART, que l'on retrouve sur la plupart des nouveaux PICs comme le PIC18F4620 (64k flash) et le  PIC18F4550 (USB), et qui affecte la stabilité du port MIDI Out
  • comme base pour un MIDI Router
  • comme possibilité d'ajouter des ports MIDI In et Out indépendant pour des projets comme la MIDIbox SEQ et la MIDIbox SID
  • comme base pour d'autres applications, dévellopées par les membres de la communauté MIDIbox! :-)

Configuration et Interconnections

le schéma du module MBHP_IIC_MIDI contients une liste exhaustive de tous les composants supportés par le firmware.

Il existe aussi une version  "OUT only", qui contient seulement les composants requis pour réaliser un simple port MIDI Out port - cette version est plus particulièrement intéressante pour ceux qui souhaitent utiliser le module pour contourner le bug EUSART. Notez que le circuit peut être allégé en retirant les LEDs  Power et Tx, mais dans ce cas le débuggage pourrait s'avérer plus difficile. En supposant que le circuit est réalisé sur une platine d'essai - ou une stripeboard, le coût pour le PIC16F88, le quartz 20 MHz, 4 condos, 4 résistances et 2 LEDs est de seulement env. 5 EUR au total!

Retournons à la version complète: l'adresse MBHP_IIC_MIDI doit être sélectionnée à l'aide de jumpers sur le port J3. Par défaut, les deux jumpers doivent être installés afin de sélectionner l'adresse 0x10. en retirant des jumpers, les addresses 0x12, 0x14 ou 0x16 peuvent être sélectionnées. Chaque module esclave a besoin d'une adresse unique sur le bus IIC, de fait n'utiliser jamais la même configuration pour plus d'un module!

Le Port J4 est un port "MIDIbox Link", qui dispose d'un MIDI IN/OUT au niveau TTL. Il peut être connecté à un module MBHP_LTC afin de dupliquer le port MIDI OUT, et pour disposer d'un port MIDI THRU. J4 peut aussi être utilisé pour une connexion vers un autre module CORE sans avoir recours à des optocoupleurs.

Le port J1 n'est pour l'instant pas utilisé, il reste libre pour de future implémentations dans le firmware.

Et pour finir, le port J2: c'est le port IIC, il se présente sous la forme de connecteur DIL afin de simplifier le cablâge en 1:1 du bus entre maître et esclaves. 4 de ses pins (Vs/Vd pour l'alimentation, SC/SD pour l'IIC) doivent être connectés aux pins du même nom du port J4 du module CORE et au port J2 "IIC_MIDI" des autres esclaves. La sortie RI# fournit un signal spécial qui indique que le buffer de réception a été chargé. Il ne sera utilisé que par un petit nombre d'applications et doit être connecté au module CORE, vous trouverez plus de détails sur les pages des projets correspondants. Si aucune indication particulière n'est donnée, laissez ce pin ouvert. Ne connectez jamais les lignes RI# des esclaves ensembles, car ceci causerait un court-circuit!

Le diagramme simplifié des inter-connections:

Une résistance pull-up de 1k est requise entre les lignes Vd et SC (normalement soudées directement au port CORE::J4) afin de permettre le "clock stretching". C'est une méthode pour retarder les transferts serie lorsqu'un esclaves ne peut répondre immédiatement à une requête du module maître. La résistance pull-up pour la connection SD est déjà installée sur le module CORE (CORE::R2).

Adaptateur de programmation pour le PIC16F88

SmashTV et Mike proposeront probablement des PIC16F88 pré-programmé dans le future, mais tant que ce service n'est pas disponible, vous devez "brûler" le firmware par vous-même dans le PIC16F88 (vous pouvez aussi demandez sur le forum) en utilisant un programmateur de PIC tel que le MBHP_BURNER.

Pour les programmateurs 40, un adapteur vers 18 pin est requis, le schéma est disponible ici.

Photos de l'adaptateur 40 pins vers 18 pins:

La tension de programmation est de 13.1V (puce PIC16F!), vous devez utiliser le programme PBrenner .

Protocole de transfert MBHP_IIC_MIDI 

Vous trouverez des détails sur le protocole I2C sur la page I2C bus specification de Philips. Tant que vous utilisez les fonctions MIOS pour accéder au module, vous n'avez pas besoin de vous soucier de ces bitstreams - continuez simplement au chapître suivant, il concerne les algorhytme d'accés. .

adresse esclave: la notation des adresses peut être source de confusion, il nous faut donc préciser d'abord que l'adresse MBHP_IIC_MIDI correspond à l'adresse esclave IIC décalée d'un bit vers la gauche (multipliée par deux). Exemple: l'adresse IIC 0x08 correspond à l'adresse MBHP_IIC_MIDI 0x10. Cette manipulation a pour but de simplifier la programmation lorsque l'on dirige le bit R/W# bit vers l'adresse. L'autre raison c'est que les adresses MBHP_IIC_MIDI sont toujours des nombres pairs.

Si 0x10 est envoyé aprés le message de début d'échange (Start), nous commençons une opération d'écriture sur le premier module MBHP_IIC_MIDI, lorsque 0x11 est envoyé, nous lançons une procédure de lecture.

Transferts vers MIDI OUT: Les transferts vers les ports OUT sont des opérations "Master Write". Aprés que le maître ait envoyé le message Start et l'adresse, il continue avec les bytes "data", qui sont directement renvoyés vers le tampon MIDI Tx du module MBHP_IIC_MIDI. Aprés le derniert byte une information de fin d'échange (Stop) doit être transmis afin de libérer le bus:

Le tampon Tx a une taille de 96 bytes. Une fois que ce tampon est plein, l'esclave répond par un "NAK" (not acknoweledge, A bit=1). Dans ce cas, le master doit transmettre un message Stop, il peut ensuite tenter de reprendre la transmission.
Un message "Restart" (Start sans état Stop préalable) n'est pas permis en raison d'un bug "sillicone" dans le module SSP de la plupart des PIC16F.

La donnée d'une valeur de "0xff" (255 en décimal) a une fonction spéciale, elle sert à activer un "mode commande". Le "mode commande" a été implémenté pour de futures extensions du firmware. Les séquences suivantes sont actuellement supportées:

  • FF 00: entrer et sortir du "mode commande", sans autre action.
  • FF FF: entrer en "mode commande", envoiyer "0xff" sur le MIDI OUT, sortir du "mode commande".
  • FF <cmd> <data1> ... <data_n>: entrer en "mode commande", appel du IIC_CMD_Handler dans le fichier iic_cmd.asm a chaque byte reçu. Le nombre maximum de byte-donnée doit être déterminé dans le gestionnaire, pour l'instant le gestionnaire sort du "mode commande" aprés le premier byte-donnée.

De fait le "mode commande" requiert la précaution suivante: si 0xff ("MIDI Reset") doit être renvoyé sur le port MIDI OUT, le maître doit envoyer ce message deux fois via l'IIC

Transfertd depuis le MIDI IN: le maître peut aussi bien scruter les états de réception via  l'IIC, ou il peut vérifier la sortie "low-active" RI# du module MBHP_IIC_MIDI (la solution la plus rapide, mais qui requiert un signal de connection supplémentaire vers le maître). En cas d'analyse via l'IIC, un message "Start condition" ainsi que l'adresse doivent être envoyés. Le flag R/W# doit être sur 1 (opération "Master Read"). Le maître peut ensuite lire le premier byte, qui contient le "type de paquet". Si il est à 0, le maître peut abandonner l'échange en envoyant un NAK et un "Stop":

Si le type de paquet n'est pas à zéro, le maître doit lire trois bytes supplémentaires:

L'encodage d'un "paquet" est inspiré des spécifications USB MIDI . L'utilisation de ce format a un avantage: un routeur MIDI->IIC->USB a besoin de renvoyer simplement le paquet au bus IN de l'hôte USB (le type de paquet correspond au CIN, et une opération OR peut être appliqué entre le "high-nibble" et le numéro de câble). Ceci simplifie également l'implémentation d'un merger MIDI, car pour tous les paquets en addition aux messages SysEx, le flow renvoyé n'a pas besoin d'être vérouiller - le module MBHP_IIC_MIDI transmets la totalité de l'évènement MIDI :
s
Type Taille Description
0x00 3 Pas de paquet - tous les bytes à zéro
0x01 3 réservé
0x02 2 messages système communs sur deux-bytes tels que MTC, Song Select, etc.
0x03 3 messages système communs sur trois-bytes comme SPP, etc.
0x04 3 "début" ou "continu" SysEx 
0x05 1 message système commun "Single-byte" ou envois sysex suivi d'un simple byte
0x06 2 envois sysex suivi de deux bytes
0x07 3 envois sysex suivi de trois bytes
0x08 3 Note Off
0x09 3 Note On
0x0a 3 Poly-Key Press
0x0b 3 Control Change
0x0c 2 Program Change
0x0d 2 Channel Preassure
0x0e 3 Changement de PitchBend 
0x0f 1 Byte simple

Algorythme d'accés MBHP_IIC_MIDI

Avec le MIOS V1.9 et supérieur, le module MBHP_IIC_MIDI peut être appellé suivant les procédures suivantes:

Redirection MIOS Tx Buffer : les opérations MIOS_MIDI_TxBufferPut peuvent être redirigées vers un esclave en sélectionnant l'adresse à l'aide de la fonction MIOS_MIDI_InterfaceSet :

 // send MIDI clock over internal MIDI Out with normal baudrate
MIOS_MIDI_InterfaceSet(MIOS_MIDI_INTERFACE_COMMON);
MIOS_MIDI_TxBufferPut(0xf8);

// send MIDI clock over MBHP_IIC_MIDI with address 0x10
MIOS_MIDI_InterfaceSet(0x10);
MIOS_MIDI_TxBufferPut(0xf8);

// switch back to default interface
MIOS_MIDI_InterfaceAutoSet();

Redirection Tx par défaut : avec le MIOS Bootloader V1.2 et supérieur, les opérations Tx buffer seront automatiquement redirigées vers le module MBHP_IIC_MIDI en établissant l'adresser dans le bit 5 de l'en-tête ID. ExEmple d'ID : 0000000000100000: envoi des données MIDI sortantes vers  MBHP_IIC_MODULE avec l'adresse 0x10. L'addresse peut toujours être changée avec MIOS_MIDI_InterfaceSet pendant le fonctionnement, et peut être remise sur son réglage par défaut avec MIOS_MIDI_InterfaceAutoSet

Fonction Réception: les fonctions suivantes peuvent être utilisée pour recevoir des paquets MIDI :

// global array which stores the package
unsigned char iic_midi_package[4];

/////////////////////////////////////////////////////////////////////////////
// This function polls the given MBHP_IIC_MIDI module for a new package
// it returns != 0 on a new package, the data will be copied into the
// global array "iic_midi_package[4]" (this is to speed up parameter passing)
/////////////////////////////////////////////////////////////////////////////
unsigned char IIC_MIDI_Receive(unsigned char addr) __wparam
{
// start IIC access
MIOS_IIC_Start();

// send address, abort if NAK received
if( !MIOS_IIC_ByteSend(addr | 1) ) {
MIOS_IIC_Stop();
return 0;
}

// receive package type, abort if type is 0x00
if( (iic_midi_package[0] = MIOS_IIC_ByteReceive()) == 0x00 ) {
MIOS_IIC_NakSend(); // abort transfer
MIOS_IIC_Stop(); // stop IIC
return 0;
}
MIOS_IIC_AckSend();

// receive three bytes
iic_midi_package[1] = MIOS_IIC_ByteReceive();
MIOS_IIC_AckSend();
iic_midi_package[2] = MIOS_IIC_ByteReceive();
MIOS_IIC_AckSend();
iic_midi_package[3] = MIOS_IIC_ByteReceive();
MIOS_IIC_NakSend();

// stop IIC access
MIOS_IIC_Stop();

return 1;
}

fonction Transmission: les fonctions suivantes peuvent être utilisée pour envoyer des paquets MIDI:

// this table contains the number of bytes depending on the package type
const unsigned char iic_midi_type_bytes[16] = { 0,0,2,3,3,1,2,3,3,3,3,3,2,2,3,1 };

/////////////////////////////////////////////////////////////////////////////
// This function sends a package to the given MBHP_IIC_MIDI module
// the package content is expected in the global array iic_midi_package[4]
// 0 is returned if the module is not available
/////////////////////////////////////////////////////////////////////////////
unsigned char IIC_MIDI_Send(unsigned char addr) __wparam
{
unsigned char retry_ctr;
unsigned char i;
unsigned char num_bytes;

// start IIC access
MIOS_IIC_Start();

// send address
retry_ctr = 0;
while( !MIOS_IIC_ByteSend(addr) ) {
// slave has sent a NAK - retry 255 times
MIOS_IIC_Stop();
if( ++retry_ctr == 255 )
return 0;
MIOS_IIC_Start();
}

// send package
num_bytes = iic_midi_type_bytes[iic_midi_package[0] & 0x0f];
for(i=0; i<num_bytes; ++i) {
retry_ctr = 0;
while( !MIOS_IIC_ByteSend(iic_midi_package[i+1]) ) {
// slave has sent a NAK - retry
// the address needs to be sent again!
MIOS_IIC_Stop();
MIOS_IIC_Start();
while( !MIOS_IIC_ByteSend(addr) ) {
MIOS_IIC_Stop();
if( ++retry_ctr == 255 )
return 0;
MIOS_IIC_Start();
}
}
}

// stop IIC access
MIOS_IIC_Stop();

// the complete package has been transmitted
return 1;
}

Notez que la fonction IIC_MIDI_Send() peut être améliorée en utilisant une fonction distincte pour envoyer l'adresse - J'ai choisi la version longue pour simplifier la lecture. Une version optimisée en assembleur est disponible dans le projet  MIDI Router .

Notez également, que cette version ne tient pas compte de la condition spéciale pour l'envoi d'un byte "0xff" via MIDI - dans la version optimisée en assembleur l'appel se fera de manière récursive. Cette méthode rendra vraiment obsolète l'exemple ci-dessus.

Routing  MIDI : les exemples ci-dessus peuvent sembler complex, mais il simplifie énormément le routing MIDI - voici un petit extraitdans lequel les paquets entrants sont renvoyés du premier module MBHP_IIC_MIDI vers le second:

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS after startup to initialize the
// application
/////////////////////////////////////////////////////////////////////////////
void Init(void) __wparam
{
// enable clock stretching
MIOS_IIC_CtrlSet(0x01);
}

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS in the mainloop when nothing else is to do
/////////////////////////////////////////////////////////////////////////////
void Tick(void) __wparam
{
if( IIC_MIDI_Receive(0x10) ) {
if( !IIC_MIDI_Send(0x12) ) {
MIOS_LCD_Clear();
MIOS_LCD_PrintCString("Slave 0x12 not connected");
MIOS_LCD_MessageStart(255);
}
}
}

Here a variant, which only forwards Control Change (CC) packages:

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS in the mainloop when nothing else is to do
/////////////////////////////////////////////////////////////////////////////
void Tick(void) __wparam
{
if( IIC_MIDI_Receive(0x10) && iic_midi_package[0] == 0x0b ) {
if( !IIC_MIDI_Send(0x12) ) {
MIOS_LCD_Clear();
MIOS_LCD_PrintCString("Slave 0x12 not connected");
MIOS_LCD_MessageStart(255);
}
}
}

Download

les modèles de PCB peuvent être ouverts, modifiés et convertis avec Eagle Light
Module Schémas Layout Aperçu
MBHP_IIC_MIDI mbhp_iic_midi.pdf mbhp_iic_midi_v3.brd mbhp_iic_midi_v3.gif
MBHP_IIC_MIDI mbhp_iic_midi_out_only.pdf non prévu -
Firmware
Fichier Taille Description
mbhp_iic_midi_v1_0c.zip 23k cette archive contient le firmware pré-compilé et les codes source pour le  PIC16F88
Informations complémentaires
Fichier Taille Description
mbhp_iic_midi_orderlist.txt 1k liste de commande chez Reichelt 

Test

Une application de bouclage logiciel (iic_midi_sw_loopback) est disponible à la section MIOS Download , qui détecte les modules esclaves connectés, et renvoie directement les évènements MIDI entrants vers les ports de sorties de ces mêmes modules MBHP_IIC_MIDI esclaves.C'est l'application parfaite pour tester les module(s), et les fichiers iic_midi.asm/iic_midi.h inclus peuvent servir de pilotes si vous souhaitez programmer une application particulière.

Quelques Photos


un module MBHP_IIC_MIDI complet connecté au module MBHP_CORE (version du PCB de SmashTV)


Deux module avec juste le MIDI-Out (version du PCB de SmashTV)

Crédits

Remerciements à SmashTV qui a créer le layout du PCB, et à Michael Klein qui m'a fourni quelques pcbs pour mes tests.



Last update: 2015-09-24

Copyright 1998-2015, Thorsten Klose. All rights reserved.