'*************************************************** ' IRQ coding for midi-in * ' by * ' Godfried-Willem Raes * ' Version 2.6 * '*************************************************** ' Interrupt-driven serial buffer for USART MIDI receive using a hardware high priority interrupt. ' This subroutine replaces the compiler's Hserin/Hrsin and HrsOut commands library subroutines ' For use with 18F devices only ' 25.09.2010 - first redaction ' 12.10.2010 - included in Pedal firmware ' 20.04.2011 - included in Fa firmware, hub ' 30.04.2011 - now user low prior. irq for sampling the sensor ' include renamed Midi_Hub_Irq.inc ' Timers include no longer required. ' 23.05.2011 - 32 bit timer coding improved ' 27.08.2012 - copied from code and reused for ' 11.10.2021 - upgraded for newest compiler version. ' 13.10.2021 - new version ready for hub board. ' Create the SYSTEM variables and aliases for the Buffered commands Dim PP0 As Byte System ' \ Dim PP0H As Byte System ' / Storage for FSR0L\H registers Dim MidiIn As Byte System Dim FSR0SaveInt As PP0 ' alias Dim FSR0SaveIntH As PP0H ' alias Dim USART_FSR0_Save As FSR0SaveInt.Word ' Alias the FSR0L\H storage to PP0\H Dim USART_FSR1_Save As Word System ' Storage for FSR1L\H registers Dim USART_FSR0 As FSR0L.Word ' alias Dim USART_FSR1 As FSR1L.Word ' alias Dim IndexIn As Byte System ' Pointer to the next empty location in the buffer Dim IndexOut As Byte System ' Pointer to the location of the oldest character in the buffer Reminders = On Warnings = On ' Point to the high priority hardware interrupt handler On_Hardware_Interrupt GoTo High_Prior_Interrupt On_Low_Interrupt GoTo Low_Prior_Interrupt GoTo _Over_IRQ_Handler ' Jump over the subroutines High_Prior_Interrupt: _Timer0_IRQ: If INTCONbits_T0IF = 1 Then Clear INTCONbits_T0IF ' Clear the Timer0 Overflow flag Inc Cnt.Word1 ' would it be slower to do Inc Cnt.Word1 instead of CntHw here? Cnt.Word0 = CntLw ' 08.12.2019 Btg PORTB,5 ' asm bit toggle - debug led watchdog Retfie Fast EndIf _UART_IRQ: If PIR1bits_RCIF = 1 Then ' Was it a USART1 byte Receive that triggered the interrupt ? Movlw 6 ' Yes. So Mask out unwanted bits Andwf RCSTA,w ' Check for errors Bnz _Uart_Error ' Was either error status bit set? USART_FSR1_Save = USART_FSR1 ' Save FSR1L\H registers Inc IndexIn ' Move up the buffer index (0-255) ' if the buffer is smaller, but still a power of 2, we can 'implement circularity simply as: 'IndexIn = IndexIn & ~USART_Buffersize 'or, if it's faster, mask the highest limit bit: 'Clear IndexIn.7 = for a 128 byte buffer 'Clear IndexIn.6 = for a 64 byte buffer USART_FSR1 = VarPtr Ringbuffer ' Point FSR1L\H to _USART_RingBuffer USART_FSR1 = USART_FSR1 + IndexIn ' Add the buffer position to FSR1L\H INDF1 = RCREG ' Place the received character into the buffer USART_FSR1 = USART_FSR1_Save ' Restore FSR1L\H registers 'Toggle PORTB.5 'debug - checked. This works. Retfie Fast ' Exit from the interrupt, restoring the WREG, STATUS, and BSR registers _Uart_Error: WREG = RCREG ' empty the 2 byte UART buffer WREG = RCREG Clear RCSTAbits_CREN ' Clear receiver status Set RCSTAbits_CREN EndIf Retfie Fast Sub GetMidiIn () If IndexIn <> IndexOut Then Inc IndexOut ' Increment IndexOut pointer (0 to 255) USART_FSR0_Save = USART_FSR0 ' Save FSR0L\H registers USART_FSR0 = VarPtr Ringbuffer ' Point FSR0L\H to Ringbuffer USART_FSR0 = USART_FSR0 + IndexOut ' Add the buffer position to FSR0L\H WREG = INDF0 ' Read buffer location (IndexOut) into WREG MidiIn = WREG ' Also place it into PP0 USART_FSR0 = USART_FSR0_Save ' Restore FSR0\H registers Set STATUSbits_C ' Set CARRY flag to indicate a byte received Ret ' compulsary here! Else WREG = 255 MidiIn = WREG ' \ Btfss STATUS,C ' Return with the CARRY flag clear to indicate timed out Ret 'compulsary here EndIf EndSub '-------------------------------------------------------------------------------- ' Initialise the USART1 interrupt ' Input : None ' Output : None ' Notes : Enables interrupt on USART1 receive. ' : Enables global and peripheral interrupts ' : If Prioritised interrupts are used, the USART interrupt priority is made high $define InitUSARTInterrupt () Init_Usart_Interrupt 'added 31.08.2010 gwr Init_Usart_Interrupt Macro GoSub _Init_Usart Endm #ifdef Init_Usart_Interrupt#Req _Init_Usart: Clear IndexIn ' Clear the buffer internal pointer Clear IndexOut ' Clear the buffer external pointer Set PIE1bits_RCIE ' Enable interrupt on USART1 receive #ifdef __Low_Interrupts_Enabled ' Are we using low priority interrupts as well ? Set IPR1bits_RCIP ' Yes. So USART1 Receive Interrupt to High priority #endif Set INTCONbits_GIE ' enable general interrups Set INTCONbits_PEIE ' Enable global and peripheral interrupts ' Set INTCONbits_T0IE ' Enable Timer0 overflow interrupt, done on opentimer0() Return #endif '-------------------------------------------------------------------------------- ' Clear the Serial Buffer ' ' Input : None ' Output : None ' Notes : Also resets the index pointers to the serial buffer $define ClearSerialBuffer () Clear_Serial_Buffer ' added 31.08.2010 - gwr Clear_Serial_Buffer Macro GoSub _Clear_Usart_Buffer Endm #ifdef Clear_Serial_Buffer#Req _Clear_Usart_Buffer: PIE1bits_RCIE = 0 ' Disable interrupt on USART1 receive Clear Ringbuffer ' Clear the serial buffer Clear IndexIn ' Clear the buffer internal pointer Clear IndexOut ' Clear the buffer external pointer Set PIE1bits_RCIE ' Re-Enable interrupt on USART1 receive Return #endif '------------------------------------------------------- ' Low Priority Interrupt on Timer3 overflow Low_Prior_Interrupt: Timer3_ISR: Context Save ' Save the contents of WREG, STATUS, and BSR Clear PIR2bits_TMR3IF ' Clear the Timer3 interrupt flag. Tim3 = 46036 ' gives 64 S/s rate, 19500 ticks, each 0.8uS, to FFFF NewVal = ADIn 0 Sensorval = SensorVal + SensorVal + SensorVal + NewVal Sensorval = Sensorval >> 2 ' 4 step integration integration - still 10 bits ' now make data window: Select sensorval Case < 256 Clear Nowval Case > 767 Nowval = 511 Case Else Nowval = sensorval - 256 EndSelect ' at this point nowval is a 9-bit value , centervalue = 255 ' make it 7-bit: Nowval = Nowval >> 2 ' 13.10.2021: Seinpos = Nowval.byte0 ' Btg blueled ' 12.12.2016: sampling rate checked on scope 192 S/s or 3 x 64 S/s Context Restore ' Restore the contents of WREG, STATUS, and BSR, then exit interrupt '------------------------------------------------------- _Over_IRQ_Handler: