'*********************************************************************************** ' Amux_V16.bas AudioKreuzschienen Steuerung 19.7.09 * ''********************************************************************************** ' V16: Neuer Befehl: z.B. 5 0 * --> Eingang 5 von allen Ausgängen trennen ' Bei Init/reset gleich Standard1 laden und in "unteren" EEProm-Bereich (der ' immer der "Arbeitsspeicher" ist), Standard2 (0 * *) kommt in "oberen" ' EEprom-Bereich und wird beim Auslesen auch sofort in den unteren kopiert '----------------------------------------------------------------------------------- ' V15n: NUR neue AVMatrix-Verschaltung angepaßt ( Data) '----------------------------------------------------------------------------------- ' V15: entweder Einzelkoppelpunkt oder alle zusammen abfragen (Btr = 32) ' Wordbyte ersetzt durch High(WORD) und Low(WORD) ' Bei Initialisierung (oder reset) gleich Standard1 laden // EEProm bleibt ! '----------------------------------------------------------------------------------- ' V14x: EEprom wird im Init-Teil NICHT gelöscht; muß EINMAL per 01* oder 02* oder per ' manueller Einstellung aktiviert werden. '*********************************************************************************** ' V14: Auswertung der empfangenen bytes in separater Sub '*********************************************************************************** ' V13: Neue Befehlsstruktur DTMF 0 (1-2) * (Bytewert 0 (1-2) 128) ' Alle Ausgangskanäle AUS: DTMF 0 0 * (0 0 128) ' Aktuelle Konfiguration als Standard2 im EEprom speichern: DTMF 0 * * (0 128 128) ' Aufruf mit: DTMF 0 2 * (0 2 128) ' 1 Standardkonfiguration und Abspeichern der aktuellen Konfiguration als 2 ' Eingabe geändert: Eingabe-, dann Ausgabekanal (NICHT -1) ' Eingabe jetzt 3 bytes; 3. byte = Schalter (nur 0, 1, * und #) ' Zeichen: DTMF PR Byte zum slave ' 0-9 0-9 0-9 ' A-D 10-13 10-13 ' * * 128 ' # # 129 '********************************************************************************** ' - Kanalnummern 1 - 16 '********************************************************************************** '* - Auslesen der Matrix Config per "Twi_master_needs_Byte": '* Bitwert (Ausgänge) werden per Overlay in Lo und Hi Byte zerlegt, '* Master-Abfrage einzeln und wieder zum WORD vereinigt (im Master) '* - ARRAY (Ch_ein(i)) : enthält Bitmuster der zugehörigen Ausgänge als WORD '* ******************************************************************************** '* 2x16 LCD: Zeile 1 = Eingabekanäle / Zeile 2 = Ausgabekanäle * '* Bei Encoderbetrieb: Cursor in der Zeile deren Werte geändert werden * '* Übernahme neuer Ausgangskonfiguration durch Extra-Taste * '********************************************************************************** '* - Kanalwahl mit Encoder per Int0 über flags (in/out=Encoder-Taste) * '* UND '* per I2C-Bus mit 3 bytes: 1. Byte = Eingangskanal, 2. Byte = Ausgangskanal '* 3. Byte Ausgangskanal EIN (1) oder AUS (0) '* Nach I2C-Eingabe wird Display neu geschrieben ' UND Matrix neu geladen ' UND Eeprom "upgedated" ' * '********************************************************************************** '*Allgemeine Definitionen '********************************************************************************** $regfile = "M8def.dat" $crystal = 8000000 ' interner RC-Oszillator '$baud = 9600 ' nur zum debuggen $framesize = 32 ' Frames $swstack = 32 ' Software stack $hwstack = 32 ' Hardware stack '************************************************************************** '* LCD-Einstellungen '************************************************************************** Config Lcdpin = Pin , Rs = Portb.0 , E = Portb.1 , Db4 = Portb.2 , Db5 = Portb.3 , Db6 = Portb.4 , Db7 = Portb.5 Config Lcdbus = 4 Config Lcd = 16 * 2 '************************************************************************** '* TWI Slave config '************************************************************************** Config Twislave = &H64 , Btr = 32 , Bitrate = 100000 ' Adresse = 100 / max 32 bytes / 100kHz $lib "i2c_twi.lbx" ' ist Teil der "i2cslave.lib" Config Scl = Portc.5 ' Config Sda = Portc.4 '************************************************************************* '* Port config: '************************************************************************* Config Portc = &B0000_1111 ' 0 - 3 output Clk Alias Portc.0 ' 4094 Pin 3 Dat Alias Portc.1 ' 4094 Pin 2 Strb Alias Portc.2 ' 4094 Pin 1 Config Portd = &B0000_0000 'Input Auf Alias Pind.0 ' für Taster Ab Alias Pind.1 ' ' ************Pind.2 (INT0) für Encoder A*********** Dschalter Alias Pind.3 ' Druckschalter am Encoder Updown Alias Pind.4 ' Encoder Pin B Neu Alias Pind.5 ' per Taster eingestellte Daten übernehmen Portd = &B0011_1111 ' pullup für 0 bis 5 Config Int0 = Change ' an Pind.2 auf Flanke warten '************************************************************************* '* Variable '************************************************************************* Dim N As Byte , I As Byte , K As Byte Dim Ekanal As Byte ' Index für Eingangskanal Dim Ch_ein(16) As Word ' Ausgangswerte zu CH_ein(n) Dim Offset As Byte ' für "oberen" EEProm-Bereich (Standard2) Dim Ch_einx As Word Dim Ch_bit(16) As Byte ' einzelne Ausgänge Dim Zeile As Byte , Pos As Byte , Pos_old As Byte ' Cursorposition (Zeile/Position) und Merker Dim Eepos As Byte ' Speicherplatz im EEProm '-------------------------- Dim Outdat As Word ' für shiftout zum Mux '--------------------------- Dim Plus As Bit ' als Interrupt flags Dim Minus As Bit Dim Neue_daten As Bit ' flag für Datenempfang vom Master '---------------------------- Dim K_aus As Word ' Dim W_aus As Word Dim Masterbyte As Byte Dim Byte_count As Byte Dim Shift_count As Word ' Dim Read_count As Byte ' Zähler beim Auslesen Dim Schalter As Byte ' Dim Kanal_status As Word ' eingeschaltet oder ausgeschaltet Dim V As Byte ' Zählvariable bei Byteanforderung durch Master Dim Dummy As Word Declare Sub Dectobin(ch_einx As Word) Declare Sub Bintodec(ch_bit(n) As Byte) '**************************************************************************************** '* Initialisierung '**************************************************************************************** $sim ' DEBUG only Osccal = &HAC ' für "exakte" 8MHz wg. UART Byte_count = 0 ' für Masterbyte Cls Waitms 25 Cursor Off Lcd "AMUX_V16" ' I'm alive ! Wait 2 Cursor On Blink Upperline Lcd "1234567890123456" ' Erste Zeile zeigt Ch_ein(n) Pos = 1 : Zeile = 1 K_aus = 1 ' beim Start/reset gleich Standard1 laden Gosub Standard_laden 'Gosub Alles_aus ' Alle Ausgänge auf AUS 'Offset = 0 ' wird bei Standard_laden miterledigt ####################### 'Gosub Write_eeprom ' und auch im "unteren" EEProm_Bereich ######################## Enable Int0 ' Interrupts erst jetzt zulassen Enable Interrupts '**************************************************************** '******************* Hauptprogramm ****************************** '**************************************************************** On Int0 Isr0 Do Debounce Dschalter , 0 , Einaus , Sub ' Toggle Zeile Debounce Neu , 0 , Neu_manuell , Sub ' setzen/löschen eines neuen Ausgangskanals Locate Zeile , Pos If Plus = 1 Then Gosub Plus ' Auswertung der Interrupt flags If Minus = 1 Then Gosub Minus If Neue_daten = 1 Then Gosub Daten_auswertung ' Auswertung der 3 neuen bytes 'Gosub Twi_gotdata ' DEBUG only Loop End '**************************************************************** '********************** Subs ************************************ '**************************************************************** '-------------- 3 neue Bytes vom Master empfangen --------------------------- Daten_auswertung: Neue_daten = 0 If Schalter = 1 Or Schalter = 0 Then Gosub Neu_i2c End If If Schalter = 128 Then If Ekanal > 0 And K_aus = 0 Then Gosub Kanal_löschen End If If Ekanal = 0 Then Select Case K_aus Case 0 Gosub Alles_aus Case 1 To 9 Gosub Standard_laden Case 128 Gosub Standard_save End Select End If End If Return '---------------------------------------------------------------* Kanal_löschen: '########################################### Ch_ein(ekanal) = 0 Ekanal = 1 Gosub Lcd0 Locate Zeile , Pos Gosub 256bitausgabe Return '------------------------------------------------------------------------------- Alles_aus: ' ... alle Ausgänge ohne Signal Dummy = 0 For N = 1 To 16 ' alle Werte auf 0 I = N Ch_ein(i) = Dummy Next N Ekanal = 1 ' mit Eingang 1 beginnen Gosub Lcd0 ' Display Konfiguration Locate Zeile , Pos Gosub 256bitausgabe ' jetzt Matrix "laden" = alles AUS Return '------------------------------------------------------------------- Standard_laden: Select Case K_aus Case 1 Restore Daten_1 For N = 1 To 16 ' Var (WORD) aus Data I = N Read Ch_ein(i) , N Next N Offset = 0 Gosub Write_eeprom ' ... und in unteren EEProm Case 2 Offset = 32 Gosub Read_eeprom ' read oberen EEProm (=Standard2) Offset = 0 Gosub Write_eeprom ' und in unteren EEProm schreiben End Select Ekanal = 1 ' mit Eingang 1 beginnen Gosub Lcd0 ' Display mit Standardkonfiguration Locate Zeile , Pos Gosub 256bitausgabe ' jetzt Matrix "laden" Return '------------------------------------------------------------- Standard_save: Offset = 32 Gosub Write_eeprom Return '------------------------------------------------------------- Plus: If Zeile = 1 Then ' Cursor in der 1. Zeile Pos = Pos + 1 If Pos > 16 Then Pos = 1 Ekanal = Pos 'Ekanal + 1 ' nächstes ch_ein Gosub Lcd0 ' ... und ch_bit(n) auf den Display Else Pos = Pos + 1 ' Cursor P eins weiter If Pos > 16 Then Pos = 1 ' Überlauf Locate Zeile , Pos ' Cursor neue Position End If Plus = 0 ' Flag wieder zurücksetzen Return '----------------------------------------------------------------- Minus: If Zeile = 1 Then Pos = Pos - 1 If Pos < 1 Then Pos = 16 Ekanal = Pos Gosub Lcd0 Else Pos = Pos - 1 If Pos < 1 Then Pos = 16 Locate Zeile , Pos End If Minus = 0 ' Flag zurücksetzen Return '------------------------------------------------------------------ Einaus: If Zeile = 1 Then ' Zeilenwechsel Zeile = 2 Pos_old = Pos Else Zeile = 1 Pos = Pos_old End If Locate Zeile , Pos Return '------------------------------------------------------------------- Neu_manuell: ' Ausgangskanal manuell neu belegen If Zeile = 1 Then Goto Raus1 ' cursor beim Eingangskanal, nix tun! If Ch_bit(pos) < 1 Then ' Kanal "leer", Ch_bit(pos) = 1 'Pos ' ...dann setzen Else Ch_bit(pos) = 0 ' sonst "leeren" End If Gosub Lcd1 ' Ch_bit Call Bintodec(ch_bit(n)) Eepos = Ekanal * 2 ' wg WORD Offset = 0 ' unteren Bereich Writeeeprom Ch_einx , Eepos ' abspeichern.... 'Ch_ein(ekanal) = Ch_einx ' um Read_eeprom zu vermeiden (falls noch nichts drin ist) Gosub Read_eeprom ' ...wieder einlesen... Gosub 256bitausgabe Raus1: Return '-------------------------------------------------------------------- Neu_i2c: ' via I2C Shift_count = K_aus - 1 W_aus = 2 ^ Shift_count Kanal_status = Ch_ein(ekanal) And W_aus ' If Schalter = 1 Then If Kanal_status = 0 Then ' wenn Ausgangskanal nicht schon gesetzt, dann Ch_ein(ekanal) = Ch_ein(ekanal) + W_aus ' Schalter = EIN : Ausgangskanal öffnen/addieren End If Elseif Schalter <> 1 Then ' If Kanal_status = W_aus Then ' wenn Ausgangskanal gesetzt, dann Ch_ein(ekanal) = Ch_ein(ekanal) - W_aus ' Schalter = AUS : Ausgangskanal schließen/subtrahieren End If End If Gosub Lcd0 ' ...und anzeigen Pos = Ekanal Gosub 256bitausgabe Return '--------------------------------------------------------------------- Lcd0: Ch_einx = Ch_ein(ekanal) Call Dectobin(ch_einx) Lcd1: Locate 2 , 1 For N = 1 To 16 I = N - 1 If Ch_bit(n) = 1 Then Lcd "*" ' Else Lcd "." ' End If Next N Return '-------------------------------------------------------- Read_eeprom: For N = 2 To 32 Step 2 ' Var (WORD) aus EEProm lesen I = N / 2 K = N + Offset ' ############################################ Readeeprom Ch_ein(i) , K ' 2er Schritte wg. Word-Format Next N Return '---------------------------------------------------------- Write_eeprom: Writeeeprom Dummy , 0 ' erster Wert geht verloren! For N = 2 To 32 Step 2 ' Var (WORD) in EEProm schreiben I = N / 2 K = N + Offset ' ############################################ Writeeeprom Ch_ein(i) , K ' 2er Schritte wg. Word-Format Next N Return '*************************************************************** '* Daten ---> Matrix (16 x 16 bit) '*************************************************************** 256bitausgabe: Strb = 0 For N = 16 To 1 Step -1 ' "hinterste" zuerst Outdat = Ch_ein(n) Shiftout Dat , Clk , Outdat , 1 ' 1 = MSB first when clock high Next N Strb = 1 Waitus 10 'Delay ' ca. 10 us Strb = 0 Return '------------------------------------- Sub Dectobin(ch_einx As Word) For N = 1 To 16 Ch_bit(n) = Ch_einx And 1 Shift Ch_einx , Right , 1 Next N End Sub '------------------------------------- Sub Bintodec(ch_bit(n) As Byte) Dim Bitwert As Word Ch_einx = 0 For N = 1 To 16 I = N - 1 Bitwert = 2 ^ I If Ch_bit(n) = 1 Then Ch_einx = Ch_einx + Bitwert End If Next N End Sub '************************************************************************* '* Interrupt Services '************************************************************************* Isr0: ' Encoder Auswertung If Pind.2 = Updown Then Plus = 1 ' Flag setzen Else Minus = 1 ' Flag setzen End If Return '------- Daten vom Master (Eingangskanal / Ausgangskanal / Schalter)--- Twi_gotdata: ' neue Daten vom Master Masterbyte = Twi ' neue Daten merken If Masterbyte > 64 And Masterbyte < 128 Then ' wegen * und # (128 und 129) V = Masterbyte - 64 Read_count = 0 ' Auslesen startet Else If Byte_count = 0 Then ' Ekanal = 0 : K_aus = 0 : Schalter = 0 ' alle einschlägigen Variablen auf 0 Ekanal = Masterbyte ' Byte_count = 1 Elseif Byte_count = 1 Then K_aus = Masterbyte ' Ausgangskanal Byte_count = 2 Elseif Byte_count = 2 Then Schalter = Masterbyte ' 1, 0, * oder # Byte_count = 0 ' wieder von vorne Neue_daten = 1 ' 3 neue bytes vom Master End If End If Return '------------------------------------ Twi_master_needs_byte: ' Reihenfolge Hi -- Lo If Read_count = 0 Then Twi = High(ch_ein(v)) Read_count = 1 Else Twi = Low(ch_ein(v)) Read_count = 0 V = V + 1 End If ' If Read_count = 0 Then ' W = 2 * V ' Read_count = 1 ' Else ' W = 2 * V ' W = W - 1 ' Read_count = 0 ' V = V + 1 ' nächstes Paar abrufen ' End If ' Twi = Wordbyte(w) Return '--------------------- müssen im Quelltext sein (nicht benutzt) --------------- Twi_stop_rstart_received: nop Return Twi_addressed_goread: nop Return Twi_addressed_gowrite: nop Return Twi_master_need_nomore_byte: nop Return '************************************************************************* '* Defaultwerte zur Initialisierung der Eingabekanäle '************************************************************************* Daten_1: ' Standard1 Data 1039% , 0% , 4096% , 1039% , 8192% , 0% ' 1(1,2,3,4,11); 2();3(13);4(1,2,3,4,11);5(14);6() Data 0% , 1039% , 0% , 0% , 0% , 0% , 0% , 0% , 0% , 0% '7(); 8(1,2,3,4,11);9-16()