Jump to content

rack switcher


ezChris

Recommended Posts

Hallo leute,

ich hab mir vorgenommen einen Midi Switcher fürs rack als Gegenstück zu einem Pedal Board zu bauen, das lediglich ein Midi Thru für das FX durchroutet (<- super anglezismus) und ein paar CCs abfängt um damit relais an einem DOUTx1 zu schalten. (ja ich bin gitarrist  ;) )

zur frage  ???:

kann man mit der midi learn funktion der MB64 auch der box sagen "hier ist deine message. daraufhin pin 1 an oder aus"? regelrecht pornös wäre es (ich weiß nicht mehr wo ichs so gesehen hab) wenn man die learn funktion dafür ummünzen konnte. also einen knopf am "ausgang" drücken und dann CC rein und gut is?

bin leider nich so fit in C++

frieden

der chris

ps: die unschuldsklausel: wenn es das thema schon gab. hab länger gesucht. wirklich!  8)

Link to comment
Share on other sites

Du willst also eigentlich keinen MIDI Switcher im Sinne von "er switcht MIDI" sondern einen "er switcht irgendwelche relais wenn er MIDI kriegt"?

Wenn ja, dann ist das ziemlich einfach, und ich würde denken eine winzige Anwedung sollte das problemlos hinkriegen. Könnte in etwa so aussehen:


mappingListe: Liste mit N Einträgen (N = anzahl der zu schaltenden Relais, jede Zeile hält den entsprechenden CC Wert)

MIDIErhalten
begin
  ist LernModus ungleich -1
    ja: schreibe in der mappingListe in der Zeile die LernModus entspricht den Wert auf den, des empfangenen CCs
        setze lernModus auf -1
        return
    nein:
      IstDerCCWertEinerDerAufEinenMeinerSchalterGemapptIst?
        ja: schalte das entsprechende Relais
        nein: tu nix.
end

learnTasterGedrückt(id des tasters)
begin
  setze Lernmodus auf ID des Schalters
end[/code]

Hmm, in der Zeit hätte ich die App schreiben können ;) Ist das in etwa das, was Du Dir vorstellst?

Link to comment
Share on other sites

wow das schnellste board der welt ;)

erm der ansatz ist richtig. ist auch nicht so schwierig.. nur das mit der einbindung. *kratz*

hatte mich auch vertan.. wollte program changes nehmen.

also eher so:

mappingListe: Liste mit N Einträgen (N = anzahl der zu schaltenden Relais, jede Zeile hält die entsprechenden PCs)

MIDIErhalten 
begin
  ist LernModus ungleich -1
    ja: schreibe in der mappingListe in der Zeile die LernModus entspricht den empfangenen PC auf
         setze lernModus auf -1
         return
    nein: 
      IstDerPCWertEinerDerAufEinenMeinerSchalterGemapptIst?
        ja: schalte das entsprechende Relais
        nein: tu nix.
end 

learnTasterGedrückt(id des tasters)
begin
  setze Lernmodus auf ID des Schalters
end

also eine zeile pro relais (ich weiß ja wieviele sofern kein array)

und dahinter steht dann ein string mit den PCs

wüsste nur bei der midibox auch garnicht wo ich das hinschreiben sollte. wahrscheinlich den original code ziehn etwas ummodeln und dann neu kompilieren. das ist richtig arbeit für jemanden der das nich jeden tag macht! hehe

Link to comment
Share on other sites

Lad Dir einfach das App Skeleton runter - da ist schon alles drin, das Du brauchst ;) Einfach einen Blick in die main.c werfen, dann wird Dir das sicher alles klarer.

Und selbst wenn Du weißt wieviele Schalter Du hast würde ich ein Array nehmen. Ist einfach schicker und deutlich flexibler (vielleicht will ja mal wer was ähnliches verwenden?) ;)

Link to comment
Share on other sites

Damit Du Dich nicht ganz so schwer tust, hier mal die Funktionen die Du brauchen wirst: Ist ungetestet, keine Ahnung ob das so geht ;)


#define SWITCH_COUNT 4
unsigned char mapping[SWITCH_COUNT]; // values could be set here already
unsigned char learnMode;

...

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS after startup to initialize the
// application
/////////////////////////////////////////////////////////////////////////////void Init(void) __wparam
{
unsigned char n;

for (n=0; n<SWITCH_COUNT; n++) // reset all triggers
mapping[n] = 255; // set to 255 (unreachable)

learnMode = 0; // turn off learn mode
}

...

/////////////////////////////////////////////////////////////////////////////
// This function is called by MIOS when an button has been toggled
// pin_value is 1 when button released, and 0 when button pressed
/////////////////////////////////////////////////////////////////////////////
void DIN_NotifyToggle(unsigned char pin, unsigned char pin_value) __wparam
{
if (pin < SWITCH_COUNT) // pin number valid?
learnMode = pin;
}

...

/////////////////////////////////////////////////////////////////////////////
//  This function is called by MIOS when a complete MIDI event has been received
/////////////////////////////////////////////////////////////////////////////
void MPROC_NotifyReceivedEvnt(unsigned char evnt0, unsigned char evnt1, unsigned char evnt2) __wparam
{
if (evnt1 >= SWITCH_COUNT) // is the program number invalid?
return;

if (evnt0 == 0xC0) { // program change
if (learnMode) { // is learnMode set?
mapping[learnMode] = evnt1; // set up the switch
} else { // no learn mode
MIOS_DOUT_PinSet(learnMode, MIOS_DIN_PinGet(mapping[evnt1]) ^ 1);
// invert the pin state
}
}
}
[/code]

Link to comment
Share on other sites

ayayay.. dafür hätte ich allerdings etwas gebraucht.  :)

kann zwar code ganz gut lesen. aber coden ohne mit dem syntax vertraut zu sein.. *puh*

  • sieht jedenfalls ganz gut aus. jetzt kommen noch ein paar schwierige stellen. in der init löscht der alles. ich möchte natürlich das dingen nicht jedesmal wenn ichs auspacke neu konfigurieren.

    und der chip wird wohl kaum seinen gesammten RAM beim ausschalten noch schnell in den flash schreiben.

    also bauen wir ne speichertaste und eine reset taste ein.. und wenn man da drauf drückt:

    MIOS_FLASH_Write(0x6660, mapping);

    und den ganzen spaß andersherum mit read bei der init. ist das korrekt? so einfach?




    • achso
      in der letzten zeile muss es glaub ich heißen:

      MIOS_DOUT_PinSet(mapping[evnt1], MIOS_DIN_PinGet(mapping[evnt1]) ^ 1);




    • danke jedenfalls schonmal fürs mitdenken.. ist übrigens noch nix außer dem burner gelötet. nurn bissel rumstochern was ich brauch und wo die möglichkeiten sind.
Link to comment
Share on other sites

MIOS_FLASH_Write(0x6660, mapping);

und den ganzen spaß andersherum mit read bei der init. ist das korrekt? so einfach?

Yep. Kann sein, dass Du @mapping[0] nehmen musst und vor allem solltest Du die Länge des Arrays dann fix auf 64 setzen.

MIOS_DOUT_PinSet(mapping[evnt1], MIOS_DIN_PinGet(mapping[evnt1]) ^ 1);

Korrekt ;)

Link to comment
Share on other sites

wenn ich am DOUT zweifarbige LEDs mit 2 pins benutzen möchte ohne transistoren usw.

reichen die 220Ohm aus um das gegen die masse abzusperren oder machen die widerstände das nich mit. geht das?

DOUT PIN - /\/\/ - · - /\/\/ - MASSE

  |

LED

  |

DOUT PIN - /\/\/ - · - /\/\/ - MASSE

/\/\/ = 220ohm

oder is das zu kurzschlüssig

der chris

Link to comment
Share on other sites

  • 4 months later...

nochmal zu dem mapping array..

1. mios kann auch multidimensional arrays oder? (unsigned char array1[128][7])

<- 128 für midi PC in

-> 1-6 welchen schalter der umlegen soll

-> 7 der midi PC out

kann ich die dann so speichern:

unsigned char n;

for (n=0; n<128; n++)	
  MIOS_FLASH_Write(0x6660+n, @array1[n][0]);
hab glaub ich nicht so ganz verstanden was das @ vor dem array bewirkt, das du mir mal erklärt hast (nils) 2. ist bei nem frisch gebrannten PIC der speicher 0? oder gehört sich auch ne init für (falls ich das dingen noch nicht benutzt hab) die den speicher formatiert? und 3. der normale midi send besteht aus:
  MIOS_MIDI_BeginStream();
  MIOS_MIDI_TxBufferPut(evnt0);
  MIOS_MIDI_TxBufferPut(evnt1);
  MIOS_MIDI_TxBufferPut(evnt2);
  MIOS_MIDI_EndStream();

right? oder gibs das auch als fertige func? *nichtgefundenhab*

grüße

Link to comment
Share on other sites

hi,

MIOS kann zwar mehrdimensionale Arrays, aber grundsätzlich dürfen arrays nicht mehr als 256 byte belegen (gibt n workaround, aber machts kompliziert und unschön :) ). da wärst du also drüber (128*7=896). du hast vermutlich vor, die felder [CC][1] bis [CC][6] entweder 1 oder 0 zu setzen, um zu bestimmen, ob das entsprechende relais schalten soll oder nicht?

erstmal achtung: zählung geht bei 0 los. wenn du also my_array[8] definierst, kannst du auf die elemente my_array[0] bis my_array[7] zugreifen.

Du brauchst ja eigentlich nicht 8bit pro relais, sondern nur eines. in einem char könntest du also alle 6 relais speichern. eine möglichkeit wäre eine AND-Verknüpfung zum lesen und eine OR-Verknüpfung zum setzen. 0x01 z.B. ist in bit aufgeschlüsselt 0b00000001, also das erste relais, 0x08 = 0b00001000 dann das 4te relais.

dein code könnte dann z.B. so aussehen

// das relais mit der nummer "learnMode" soll dem CC Nr. "ccNumber" zugewiesen werden

array1[ccNumber] |= MIOS_HLP_GetBitORMask(learnMode);
// MIOS_HLP_GetBitORMask gibt dir zu einer Zahl einen Wert zurück, bei dem nur das bit an der stelle "Zahl" gesetzt ist,
// also z.B. learnMode == 4  =>  MIOS_HLP_GetBitORMask(learnMode) == 0b00001000
// zu einem CC sollen die richtigen relais ausgelöst werden

for (relais_nr =0; relais_nr <= 5; ++relais_nr ) {
  relais_set = MIOS_HLP_GetBitORMask(relais_nr ) & array1[cc_number ];
  // z.B. cc_number = 28, relais_nr = 4, array1[28] = 0b00001001 => relais_set == 0x08; da ungleich null, wird das 4te relais geschaltet
  MIOS_DOUT_PinSet(relais_nr, relais_set );
}

wegen dem speichern: soweit ich das mitbekommen hab, sollte man eigentlich ein schreiben in den flashspeicher zur laufzeit vermeiden oder? (gefahr, irgendeinen programmteil zu überschreiben etc.) stattdessen lieber einen bankstick hernehmen. oder habt ihr da keine bedenken?

zu 2.: so ganz hab ich nicht verstanden, was du mit "speicher 0" meinst, dass der speicher komplett leer ist? wenn du ihn jungfräulich kaufst, dann ja. als nächstes musst du dann den bootloader mit deinem mbhp_burner draufbrennen, dann über midi das Betriebssystem MIOS aufspielen. jetzt kannst du über midi deine Anwendungen aufspielen. entweder ne fertige andwendung wie z.B. Midibox64 oder eine eigene, die du idR aus einem SDCC-Skelett mit deinem Code oder aus einer modifizierten Anwendung compilierst.

und zu 3.: genau! in ne funktion verpacken müsstest du das selber. Wobei mir noch nicht so ganz klar ist, wann man das ...BeginStream und ...EndStream braucht. bei mir steht das nirgends dabei. Wird damit MIOS_MIDI_TxBufferPut aus anderen Funktionen heraus blockiert?

Grüße und viel Spaß beim Basteln :)

Alex

Link to comment
Share on other sites

hey alex,

danke für die antwort..

zu 1.)

wusste nicht dass man arrays nur mit 256byte belegen darf. würd dann zwar ein byte für alle buttons benutzen aber das nicht mit der mask variante machen sondern die bytes bitweise auslesen per:

byte & 0x01 != 0; (1.bit)
byte & 0x02 != 0; (2.bit)
byte & 0x04 != 0; (3.bit)
byte & 0x08 != 0; (4.bit)
byte & 0x10 != 0; (5.bit)
byte & 0x20 != 0; (6.bit)

damit man auch den 1. und 2. schalter gleichzeitig aktivieren kann..

dann wär der array 128*2 macht genau die 256..! porno! ;-)

zu 2.)

wenn ich zum ersten mal mein gerät anschalte und der den flash ausliest. ist der dann leer oder bastelt er sich ne einstellung zusammen weil im speicher lauter müll rumturnt. ich glaub der bootloader formatiert aber den flash einmal komplett.. sofern ist die frage geklärt.

zu 3.)

das beispiel hab ich von der ucapps seite. steht unter mios/Functions im mennü

grüße

Link to comment
Share on other sites

hey Chris,

mein code beispiel kann auch mehrere relais setzen. wenn du beim schreiben ein OR (resp. | ) hernimmst, bleiben alle anderen bits unverändert, ausser dem, wo die maske eine 1 enthält. du kannst also für einen CC erst relais 1 setzen und später auch noch relais 5. dazunehmen, so dass beide schalten, wenn der entsprechende CC ankommt. der vorteil der OrMask ist, dass du nicht eine Routine für jedes relais schreiben musst, also in deinem beispiel die expliziten abfragen mit 0x01 bis 0x20. die OrMask generiert dir genau diese Zahl, wenn du ihr die nummer des Relais gibst. wenn du also das 6te relais überprüfen willst, übergibst du 0x05 == 0b00000101 (wir zählen von 0) und bekommst als ergebnis 0x20 == 0b00100000.

hab ganz vergessen, dass man ja evntl. auch relais wieder löschen möchte. um relais 3 zu löschen brauchst du dann

array1[ccNumber] &= 0b11111011; // == 0xFB 
das lässt alle anderen relais-einstellung unverändert und löscht nur relais 3. alternativ mit der Maskenfunktion:
array1[ccNumber] &= MIOS_HLP_GetBitANDMask(learnMode);

ich bin mal davon ausgegangen, dass in allen beispielen, die variable "learnMode" die Relais-Nummer enthält, um die gleichen Namen wie Nils zu verwenden.

was mir gerade einfällt: es gibt doch die midibox cv. hast du dir die schonmal angeschaut? evtl. kann die schon alles was du brauchst.  wenn auch selbermachen natürlich wesentlich cooler is :)

Grüße, Alex

Link to comment
Share on other sites

hi danke für die antwort,

ich denke wie ich da an die pins komm und die aus nem char raushol klappt ganz gut mit internet recherche etc. ..

frag mich eher wie das mit dem speichern so klappt.

vorallem was das @ vor dem array zu suchen hat. hab sowas nirgends gefunden.

und darf man nu während der laufzeit auf den flash zugreifen. ich mein 'hab mir mal n eeprom bestellt. hat mich auch nicht in den finanziellen abgrund gestoßen. aber wüssen würd ichs schon gern ;-)

der chris

ps: selber programmieren rockt. weil mehr überblick und weil danach kommt die fußleiste zu dem rackteil. und das wird dann noch mehr special.

Link to comment
Share on other sites

hmm, ich kann mir auch keinen richtigen reim drauf machen, wie Nils das gemeint hat. ich glaub ja fast, er hat sich vertippt und meinte eigentlich "&mapping[0]" :) wobei das eigentlich auf exakt das gleiche rauskommen sollte wie "mapping".

bzw. in deinem beispiel sollte mMn "&array1[n][0]" dasselbe wie "array1[n]" sein. keine ahnung was das ausmachen soll  ???

wegen dem flash: funktionieren sollte es wohl. so wie ich das mitbekommen hab, ist n bankstick aber der saubere weg, um solche daten zu speichern. und einfacher wahrscheinlich auch. kannst einfach ab adresse 0x0000 loslegen und musst dir keine gedanken machen.

Link to comment
Share on other sites

mist, dachte, ich editier das noch ganz schnell rein, aber hast genau in dem moment gepostet  :P

ich hab ja selber noch kaum erfahrung. bin auch grad dabei, meiner anwendung, bei der alles fest gecoded is, presets beizubringen. steh aber auch noch in der planungsphase, welche daten muss ich sichern, wie organisier ich die, etc. Finds auf jeden Fall ziemlich spannend alles :)

evtl. kannst ja nils ne pm schicken, wie das @ gemeint hat. und vor allem wozu :)

Link to comment
Share on other sites

ich dachte eigentlich, dass genau dafür das & da ist ^^. muss mal kucken, ob das sdcc anders handhabt, aber würde mich eigentlich wundern. und wenn man ein array benutzt, ohne einen index anzugeben, dann bekommt man normalerweise auch einen pointer, der auf den speicher zeigt, an dem das array anfängt.

hab mir grad ne C-Referenz und die anleitung zu sdcc angeschaut, aber nirgends ein @ gefunden...

Link to comment
Share on other sites

Ein Array ist als Datentyp immer ein Pointer. Deswegen kann man implizit Arrays auch als Zeiger und umgekehrt verwenden,

inkl. Zeigerarithmetik zum Direktzugriff auf Arrayelemente.

Das @ wird vermutlich eine SDCC-spezifische Präprozessorerweiterung sein, Bestandteil des Standards ist das Token jedenfalls nicht.

Mit dem SDCC kenne ich mich persönlich allerdings nicht gut genug aus, um die Funktionalität dieses Tokens eindeutig beantworten zu können.

Hoffentlich war das trotzdem hilfreich :)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...