;********************************************************************** ;** Midi Exiter 0.15 -- son of Midip ** ;********************************************************************** ; The main program and less stable routines of the Midi Exiter. Midip ; was an ill-fated, never completed MIDI project I started in the mid 80's. ; To be build on wire-wrapped boards and Z80 based, it was a Pad-to-MIDI ; converter. The keyboard and display are reused in the Midi Exiter. ; Files copyrighted by F.J. Kraan unless indicated otherwise. When all ; foreign routines are replaced, the set will be released under GPL (or ; maybe sold for large sums of money :-) ). .include "4433def.inc" ; Generic registers .def rxchar = r04 .def midichan = r05 .def midistat = r06 .def midictrn = r07 .def savesreg = r08 .def scanbut = r09 ; value of the scanned buttons .def adctmp = r10 .def nibstore = r11 ; storage of the other nibble .def test = r13 .def hexlsn = r14 ; least significant nibble in hex .def hexmsn = r15 ; most significant nibble in hex ; Extended generic registers (sbci, subi, cpi, andi, ori, ldi) .def send = r16 ; midi send flag and value .def temp = r17 ; generic variable .def temp2 = r18 ; extra generic variable .def ldelcnt = r19 ; long delay count .def sdelcnt = r20 ; short delay count .def txtadr = r21 ; address of the eeprom text string .def cursor = r22 .def adc4 = r23 .def adc5 = r24 .def busych = r25 .def intrflag = r26 .def adcdummy = r27 ;Xtal oscillator frequency .equ Clock = 8000000 ;Baud rate for MIDI .equ Baud = 31250 ; Post version correction. .equ UbrrVal = Clock/(Baud*16)-1 ;Timer value to get 1 second interrupts .equ Timer1Val = 31250 ;Midi values .equ ActSens = 0xFE .equ SysReset = 0xFF ;Display control patterns and values port B .equ Lcd_Ctrl = PORTB ; Control port alias .equ Lcd_RW = 0 ; R/W on bit 0 .equ Lcd_RS = 1 ; RS on bit 1 .equ Lcd_E = 2 ; E on bit 2 ;Display control patterns and values port D .equ Lcd_Data = PORTD ; Data port alias .equ Lcd_DtMsk = 0b11110000 ; Mask out low nibble of data byte .equ Lcd_RDPat = 0b00000000 ; Data direction mask for LCD read .equ Lcd_WRPat = 0b11110000 ; Data direction mask for LCD write ;Keyboard port aliasses, masks and values .equ ButRows = PINC .equ ButCol = PORTB .equ FncCol = 5 .equ NavCol = 4 .equ ButMask = 0x0F ;Display addresses .equ Adc1Pos = 0x43 .equ Adc2Pos = 0x49 .equ But1Pos = 0x58 .equ But2Pos = 0x57 .equ But3Pos = 0x56 .equ But4Pos = 0x55 .equ But5Pos = 0x54 .equ But6Pos = 0x53 .equ But7Pos = 0x52 .equ But8Pos = 0x51 .equ BusyPos = 0x27 ;Display busy characters .equ BusyCh0 = '-' .equ BusyCh1 = 0b0000000 ; For HD44780A00 Japanese font only. Otherwise use '\' .equ BusyCh2 = '|' .equ BusyCh3 = '/' ;Definition data backslash for Japanese font .equ CG_BS0 = 0b00000000 .equ CG_BS1 = 0b00010000 .equ CG_BS2 = 0b00001000 .equ CG_BS3 = 0b00000100 .equ CG_BS4 = 0b00000010 .equ CG_BS5 = 0b00000001 .equ CG_BS6 = 0b00000000 .equ CG_BS7 = 0b00000000 .equ CG_Char0 = 0b01000000 ;Definition data copyright .equ CG_Copy0 = 0b00001110 .equ CG_Copy1 = 0b00010101 .equ CG_Copy2 = 0b00011011 .equ CG_Copy3 = 0b00011001 .equ CG_Copy4 = 0b00011011 .equ CG_Copy5 = 0b00010101 .equ CG_Copy6 = 0b00001110 .equ CG_Copy7 = 0b00000000 .equ CG_Char1 = 0b01001000 ;********************************************************************** ;** SRAM ** ;********************************************************************** .dseg .org 0x60 RXRBUF: .org 0x70 TXRBUF: .org 0x80 ;********************************************************************** ;** FLASH ** ;********************************************************************** .cseg .org 0x000 ; kommt ganz an den Anfang des Speichers rjmp RESET ; Interruptvektoren überspringen ; und zum Hauptprogramm .org INT0addr rjmp EXT_INT0 ; IRQ0 Handler .org INT1addr rjmp EXT_INT1 ; IRQ1 Handler .org ICP1addr rjmp TIM1_CAPT ; Timer1 Capture Handler .org OC1Aaddr rjmp TIM1_COMP ; Timer1 Compare Handler .org OVF1addr rjmp TIM1_OVF ; Timer1 Overflow Handler .org OVF0addr rjmp TIM0_OVF ; Timer0 Overflow Handler .org SPIaddr rjmp SPI_STC ; SPI Transfer Complete Handler .org URXCaddr rjmp USART_RXC ; USART RX Complete Handler .org UDREaddr rjmp USART_DRE ; UDR Empty Handler .org UTXCaddr rjmp USART_TXC ; USART TX Complete Handler .org ADCCaddr rjmp ADC ; ADC Conversion Complete Interrupt Handler .org ERDYaddr rjmp EE_RDY ; EEPROM Ready Handler .org ACIaddr rjmp ANA_COMP ; Analog Comparator Handler RESET: ; Stack pointer ldi temp, low(RAMEND) out SPL,temp ; Configure Baudrate ldi temp, LOW(UbrrVal) out UBRRL, temp ldi temp, HIGH(UbrrVal) out UBRRH, temp sbi UCSRB, TXEN ; TX activeren ; Port initialisation ldi temp, LCD_WRPat ; PD 0,1 input, 2-7 output out DDRD, temp ldi temp, 0x00 ; PC input out DDRC, temp ldi temp, 0xFF ; PB output out DDRB, temp ; Interrupt definition ; Inputs ; ldi temp, 0b00001010 ; INT0 en INT1 configureren ldi temp, 0b00000000 ; INT0 en INT1 configureren out MCUCR, temp ; ldi temp, 0b11000000 ; INT0 en INT1 activeren ldi temp, 0b00000000 ; INT0 en INT1 deactiveren out GIMSK, temp ; Timer ldi temp, 0b00000000 ; out TCCR1A, temp ldi temp, 0b00000100 ; CK/256 prescaler out TCCR1B, temp ldi temp, HIGH(Timer1Val) ; MSB out TCNT1H, temp ldi temp, LOW(Timer1Val) ; LSB out TCNT1L, temp ldi temp, 0b10000000 ; TOV1 set out TIFR, temp ldi temp, 0b10000000 ; TOIE1 set out TIMSK, temp ; ADC ldi temp, 0b00000100 ; Select channel 4 out ADMUX, temp ldi temp, 0b11001111 ; Enable, start, single run, int, /128 prescale out ADCSR, temp ; USART sbi UCSRB, RXEN ; Receiver enable sbi UCSRB, RXCIE ; Character received interrupt enable sei ; Main interrupt activate ldi send, 0 ldi intrflag, 0 ldi adcdummy, 0 rcall LCD_INIT rcall LCD_HOME ldi txtadr, BANNERTXT rcall DISPTXT ldi cursor, 0x40 rcall LCD_PRINTAT ldi txtadr, DBUGSTRING rcall DISPTXT LOOP: tst intrflag breq LOOP_1 rcall BUSYCHAR ldi intrflag, 0 LOOP_1: tst send breq LOOP mov temp, send ldi send, 0 rcall SEROUT ; ldi cursor, 0x24 ; rcall LCD_PRINTAT rcall READBUTTON ; mov temp, scanbut ; rcall BIN2HASC ; mov temp, hexmsn ; rcall LCD_DTWR ; mov temp, hexlsn ; rcall LCD_DTWR rcall KEYACTION mov temp, adc4 rcall BIN2HASC ldi cursor, ADC1Pos rcall LCD_PRINTAT mov temp, hexmsn rcall LCD_DTWR mov temp, hexlsn rcall LCD_DTWR mov temp, adc5 rcall BIN2HASC ldi cursor, ADC2Pos rcall LCD_PrintAt mov temp, hexmsn rcall LCD_DTWR mov temp, hexlsn rcall LCD_DTWR rjmp LOOP ; SEROUT: sbis UCSRA,UDRE ; Check for previous sent byte rjmp SEROUT ; and wait until it is finished out UDR, temp ret KEYACTION: ldi cursor, BUT1POS rcall LCD_PRINTAT ldi temp, 0 ldi temp2, '0' sbrs scanbut,0 inc temp add temp, temp2 rcall LCD_DTWR ldi cursor, BUT2POS rcall LCD_PRINTAT ldi temp, 0 sbrs scanbut,1 inc temp add temp, temp2 rcall LCD_DTWR ldi cursor, BUT3POS rcall LCD_PRINTAT ldi temp, 0 sbrs scanbut,2 inc temp add temp, temp2 rcall LCD_DTWR ldi cursor, BUT4POS rcall LCD_PRINTAT ldi temp, 0 sbrs scanbut,3 inc temp add temp, temp2 rcall LCD_DTWR ldi cursor, BUT5POS rcall LCD_PRINTAT ldi temp, 0 sbrs scanbut,4 inc temp add temp, temp2 rcall LCD_DTWR ldi cursor, BUT6POS rcall LCD_PRINTAT ldi temp, 0 sbrs scanbut,5 inc temp add temp, temp2 rcall LCD_DTWR ldi cursor, BUT7POS rcall LCD_PRINTAT ldi temp, 0 sbrs scanbut,6 inc temp add temp, temp2 rcall LCD_DTWR ldi cursor, BUT8POS rcall LCD_PRINTAT ldi temp, 0 sbrs scanbut,7 inc temp add temp, temp2 rcall LCD_DTWR ret .include "midiexiter_lib.asm" ;********************************************************************** ;** Interrupt service routines from here ** ;********************************************************************** EXT_INT0: EXT_INT1: TIM1_CAPT: TIM1_COMP: reti TIM1_OVF: in savesreg, SREG ldi intrflag, 1 cbi PORTB, 3 ldi temp, HIGH(TIMER1VAL) ; MSB out TCNT1H, temp ldi temp, LOW(TIMER1VAL) ; LSB out TCNT1L, temp ldi send, SysReset out SREG, savesreg reti TIM0_OVF: SPI_STC: USART_RXC: in savesreg, SREG in rxchar, UDR tst send ; Check if a character is being send brne TXBUSY ; If so, skip the received character mov send, rxchar TXBUSY: out SREG, savesreg reti USART_DRE: USART_TXC: reti ADC: in savesreg, SREG tst adcdummy ; Check dummy conversion flag brne ADCDMINT ; Exit if set ADC4: sbic ADMUX, 0 ; If this bit is set, ADC5 is active rjmp ADC5 sbi ADMUX, 0 ; ADC4 is active. Switch channel to ADC5 ldi adcdummy, 1 in adctmp, ADCL in adc4, ADCH sbi ADCSR, 6 ; Start next conversion lsr adctmp lsr adctmp lsr adctmp swap adc4 lsl adc4 or adc4, adctmp cbr adc4, 0x80 out SREG, savesreg reti ADC5: cbi ADMUX, 0 ; ADC5 is active. Switch channel to ADC4 ldi adcdummy, 1 ; Set dummy conversion flag in adctmp, ADCL in adc5, ADCH sbi ADCSR, 6 ; Start next conversion lsr adctmp lsr adctmp lsr adctmp swap adc5 lsl adc5 or adc5, adctmp cbr adc5, 0x80 out SREG, savesreg reti ADCDMINT: sbi ADCSR, 6 ; Start next conversion ldi adcdummy, 0 ; Reset dummy conversion flag out SREG, savesreg reti EE_RDY: ANA_COMP: reti ;********************************************************************** ;** EEPROM ** ;********************************************************************** .eseg .org 0x00 EmptyPos: ;leave eeprom location 00 empty due to bug .db 00 ;in AVR that randomly erases the contents BANNERTXT: ;What the LCD will display on power up .db "Electrickery MIDI Exiter 0.15 ",01,"2003",00 DBUGSTRING: .db "A0: A1: B7-0:",00 ;Strings are 0 ended .org 0xF0 EEMIDICHANNEL: .db 0x00 EEMIDISTATUS: .db 0b00001011 EEMIDICTRLNO: .db 0b00000001