• Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

complete code for midi to emulated PS/2 keyboard. PLEASE HELP!!

Status
Not open for further replies.

facemanfacey

New Member
hi i have been working on this code for a while now and i have come to a complete dead end. the following code takes midi data on the rx pin of the usart, saves the 3 bytes of data in the cblock, tests the first byte to see if it is a midi on message (xxxx1001) by masking the upper nibble and subtracting from a constant to see if it equals zero, if so take the next byte, convert it using the lookup table. THEN send this data via ra0 and ra1 in a loop which emulates a ps/2 keyboard after calculating the odd parity bit.

first things first, i wrote the diagnostic LED part which doesn't work, led 1 is constantly ON and led2 flashes on, then off, then is constantly on, AND THEN led 3 won't even come on.

so could you please look through my code to see if there are any faults in my programing or if you think there is probably a circuit design problem?

(the trisa and trisb port setup has been tried with the bytes reversed and it still gives the same problem ie 10100000 instead of 00000101)

thank you in advance for your help!

thomas


Code:
;------------------------------------------------------------------------------
; PROCESSOR DECLARATION
;------------------------------------------------------------------------------

     LIST      p=16F88              ; list directive to define processor
     #INCLUDE <P16F88.INC>          ; processor specific variable definitions

;------------------------------------------------------------------------------
; CONFIGURATION WORD SETUP
;------------------------------------------------------------------------------

     __CONFIG    _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_ON & _WDT_OFF & _HS_OSC
     __CONFIG    _CONFIG2, _IESO_OFF & _FCMEN_OFF

;------------------------------------------------------------------------------
; VARIABLE DEFINITIONS
;------------------------------------------------------------------------------

    CBLOCK 0x20 		; data block allocated to data bytes
        BYTE1  			; midi byte 1
        BYTE2  			; midi byte 2
        BYTE3  			; midi byte 3
	TEMP_ON			; temp store for testing midi on byte  
	PARITY_TEMP 	        ; temp store for calculating parity bit
	PARITY_BYTE		; whole byte for parity bit storage
	PARITY_COUNT	        ; parity counter to count down from 8
	KEYBOARD		        ; data for transmission
	TRANSMIT_COUNT	; counter for transmitted bits
	D1				; temp for delay routine
	D2				; temp for delay routine
	D3				; temp for delay routine
	D4				; temp for delay routine
	D5				; temp for delay routine
	D6				; temp for delay routine
	D7				; temp for delay routine
   ENDC


PARITY              EQU     	          0x00      ; single bit defined for parity bit
LSB			EQU			  0x00        ; LSB of keyboard 
LED1		   	EQU			  0X02	 ; RA2
LED2		   	EQU			  0X03	 ; RA3
LED3			EQU			  0X03	 ; RB3
CLOCK		EQU			  0X00	 ; RA0
DATALINE		EQU			  0X01	 ; RA1


W_TEMP         	EQU        0x7D  ; w register for context saving (ACCESS)
STATUS_TEMP    	EQU        0x7E  ; status used for context saving (ACCESS)
PCLATH_TEMP    	EQU        0x7F  ; variable used for context saving

;------------------------------------------------------------------------------
; EEPROM INITIALIZATION The 16F88 has 256 bytes of non-volatile EEPROM, 
; starting at address 0x2100
;------------------------------------------------------------------------------

DATAEE    ORG  0x2100
    DE    "MCHP"  ; Place 'M' 'C' 'H' 'P' at address 0,1,2,3

;------------------------------------------------------------------------------
; RESET VECTOR
;------------------------------------------------------------------------------

RESET     ORG     0x0000            ; processor reset vector
          PAGESEL START
          GOTO    START             ; go to beginning of program

;------------------------------------------------------------------------------
; INTERRUPT SERVICE ROUTINE
;------------------------------------------------------------------------------

ISR       ORG     0x0004            ; interrupt vector location

;         Context saving for ISR
          MOVWF   W_TEMP               ; save off current W register contents
          MOVF    STATUS,W             ; move status register into W register
          MOVWF   STATUS_TEMP       ; save off contents of STATUS register
          MOVF    PCLATH,W              ; move pclath register into W register
          MOVWF   PCLATH_TEMP       ; save off contents of PCLATH register

;------------------------------------------------------------------------------
; USER INTERRUPT SERVICE ROUTINE GOES HERE
;------------------------------------------------------------------------------

;         Restore context before returning from interrupt
          MOVF    PCLATH_TEMP,W     ; retrieve copy of PCLATH register
          MOVWF   PCLATH            ; restore pre-isr PCLATH register contents
          MOVF    STATUS_TEMP,W     ; retrieve copy of STATUS register
          MOVWF   STATUS            ; restore pre-isr STATUS register contents
          SWAPF   W_TEMP,F
          SWAPF   W_TEMP,W          ; restore pre-isr W register contents
          RETFIE                    ; return from interrupt

;------------------------------------------------------------------------------
; MAIN PROGRAM
;------------------------------------------------------------------------------

START

INITIALIZE_PORTS
	
	CLRF	CCP1CON
	BCF 	STATUS,RP1			; select bank 1
	BSF 	STATUS,RP0
	MOVLW	B'10100000'			; setting up PORTA
	MOVWF 	TRISA
	MOVLW	B'00000100'			; setting up PORTB
	MOVWF 	TRISB
	MOVLW 	D'39'				; 31250 baud rate
	MOVWF 	SPBRG 				
	MOVLW 	B'00000100'			; set up high speed BRGH 
	MOVWF 	TXSTA
	MOVLW	B'10010000'			; set up asynchronous reception
	MOVWF	RCSTA


DIAGNOSTIC_LEDS

	BSF 	PORTA,LED1 			; blink LED1
	CALL 	DELAY200ms
	BCF 	PORTA,LED1
	CALL 	DELAY200ms

	BSF 	PORTA,LED2			; blink LED2
	CALL 	DELAY200ms
	BCF 	PORTA,LED2
	CALL 	DELAY200ms

	BSF 	PORTB,LED3			; blink LED3
	CALL 	DELAY200ms
	BCF 	PORTA,LED3
	CALL 	DELAY200ms

LOOP1

	BTFSS 	PIR1,RCIF 	       ;Wait for RX flag
	GOTO 	LOOP1 		;wait for USART byte
	MOVF 	RCREG,W		;move first midi byte to w 
	MOVWF	BYTE1		;store in memory location
	MOVWF	TEMP_ON		;store in temp location for manipulation

LOOP2

	BTFSS 	PIR1,RCIF 	       ;Wait for RX flag
	GOTO 	LOOP2 		;wait for USART byte	
	MOVF 	RCREG,W		;move second midi byte to w 
	MOVWF	BYTE2		;store in memory location to free up RCREG

LOOP3

	BTFSS 	PIR1,RCIF 	        ;Wait for RX flag
	GOTO 	LOOP3 		;wait for USART byte	
	MOVF 	RCREG,W		;move third midi byte to w 
	MOVWF	BYTE3		;store in memory location to free up RCREG
	
NOTE_ON_TEST

	MOVLW	TEMP_ON
	ANDLW	0x0F
	SUBLW	B'00001001'
	BTFSC	STATUS,Z
	GOTO  	NOTE_ON
	GOTO 	DISREGARD	

NOTE_ON					;convert byte 2 and move to memory location for transmission

	MOVF	        BYTE2,W
	CALL	        TABLE
	MOVWF	KEYBOARD
	CALL	        PARITY_CALC
	CALL	        TRANSMIT

DISREGARD				;used to free up RCREG for next midi transmission

	CLRF	       BYTE1
	CLRF	       BYTE2
	CLRF	       BYTE3
	GOTO 	LOOP1 

;**********************************************************************************************************************
;   Calculates tha parity bit expected from the keyboard
;**********************************************************************************************************************

PARITY_CALC                               ; This routine counts the number of ones that are in the work reg

        movwf  	PARITY_TEMP               ; Save the byte that is to be checked in a file reg
        clrf   	        PARITY_COUNT                ; Clear result file reg
 
        movlw  	0x08
        movwf  	PARITY_COUNT              ; Do all 8 bits (set counter)

PARITY_LOOP
        rrf    	       PARITY_TEMP, f            ; Check next bit

        btfsc  	STATUS, C            	  ; Increase counter if a bit was detected as a one
        incf   	PARITY_COUNT, f

        decfsz 	PARITY_COUNT, f      	  ; Exit loop if all 8 bits done
        goto   	PARITY_LOOP

        bcf            PARITY_BYTE, PARITY       ; Parity-bit for the routine "keyboard" is stored in PARITY_BYTE file
        btfss          PARITY_COUNT, LSB     	  ; Odd parity
        bsf            PARITY_BYTE, PARITY

        return

;------------------------------------------------------------------------------------------
; emulated PS2 output
;------------------------------------------------------------------------------------------

TRANSMIT
 
        movlw 	0x08
        movwf 	TRANSMIT_COUNT

        bcf 	PortB, DATALINE            ;Begin transfer (Startcondition)
        call 	DELAY20
        bcf 	PortB, CLOCK
        call 	DELAY20
        call 	DELAY20

TRANSMIT_LOOP

        bsf 	PortB, CLOCK
        call 	DELAY20

        btfss 	KEYBOARD, LSB            ;Output character - bit for bit (LSB first)
        bcf 	PortB, DATALINE
        btfsc KEYBOARD, LSB
        bsf 	PortB, DATALINE
        rrf 	KEYBOARD, 1

        call 	DELAY20
        bcf 	PortB, CLOCK
        call 	DELAY20
        call 	DELAY20

        decfsz 	TRANSMIT_COUNT, 1
        goto   	TRANSMIT_LOOP

        bsf 	PortB, CLOCK
        call 	DELAY20

        btfss 	PARITY_BYTE, PARITY        ;Output parity bit
        bcf 	PortB, DATALINE
        btfsc PARITY_BYTE, PARITY
        bsf 	PortB, DATALINE
        call 	DELAY20

        bcf 	PortB, CLOCK
        call 	DELAY20
        call 	DELAY20
        bsf 	PortB, CLOCK

        call 	DELAY20
        bsf 	PortB, DATALINE
        call 	DELAY20

        bcf 	PortB, CLOCK
        call 	DELAY20
        call 	DELAY20
        bsf 	PortB, CLOCK

        rrf 	KEYBOARD, 1 		          ;Transfer complete
        return


;-----------------------------------------------------------------------------
;  Delay loops, 20us delay needs 100 instruction cycles 
;			    0.1s needs 500000 instruction cycles
;			    0.2s needs 1000000 instruction cycles	
;-----------------------------------------------------------------------------

DELAY20						;100 cycles
	movlw	0x21
	movwf	D1
DELAY20_0
	decfsz	D1, f
	goto	DELAY20_0
	return

DELAY200ms					;999990 cycles
	movlw	0x07
	movwf	D2
	movlw	0x2F
	movwf	D3
	movlw	0x03
	movwf	D4
DELAY200ms_0
	decfsz	D2, f
	goto	$+2
	decfsz	D3, f
	goto	$+2
	decfsz	D4, f
	goto	DELAY200ms_0
	goto	$+1				;6 cycles
	goto	$+1
	goto	$+1
	return					;4 cycles

DELAY100ms					;499994 cycles
	movlw	0x03
	movwf	D5
	movlw	0x18
	movwf	D6
	movlw	0x02
	movwf	D7
DELAY100ms_0
	decfsz	D5, f
	goto	$+2
	decfsz	D6, f
	goto	$+2
	decfsz	D7, f
	goto	DELAY100ms_0    
	goto	$+1				;2 cycles
	return					;4 cycles





;-----------------------------------------------------------------------------
;  Look up table
;-----------------------------------------------------------------------------

TABLE ADDWF	PCL,1
	RETLW 0x0E
	RETLW 0x0D
	RETLW 0x15
	RETLW 0x1E
	RETLW 0x1D
	RETLW 0x26
	RETLW 0x24
	RETLW 0x2D
	RETLW 0x2E
	RETLW 0x2C
	RETLW 0x36
	RETLW 0x35
	RETLW 0x3D
	RETLW 0x3C
	RETLW 0x43
	RETLW 0x46
	RETLW 0x44
	RETLW 0x45
	RETLW 0x4D
	RETLW 0x54
	RETLW 0x55
	RETLW 0x5B
	RETLW 0x12
	RETLW 0x58
	RETLW 0x1A
	RETLW 0x22
	RETLW 0x1B
	RETLW 0x21
	RETLW 0x23
	RETLW 0x2A
	RETLW 0x32
	RETLW 0x34
	RETLW 0x31
	RETLW 0x33
	RETLW 0x3A
	RETLW 0x3B
	RETLW 0x41
	RETLW 0x49
	RETLW 0x4B
	RETLW 0x4A
	RETLW 0x4C
	RETLW 0x52
	RETLW 0x59
	RETLW 0x0E
	RETLW 0x0D
	RETLW 0x15
	RETLW 0x1E
	RETLW 0x1D
	RETLW 0x26
	RETLW 0x24
	RETLW 0x2D
	RETLW 0x2E
	RETLW 0x2C
	RETLW 0x36
	RETLW 0x35
	RETLW 0x3D
	RETLW 0x3C
	RETLW 0x43
	RETLW 0x46
	RETLW 0x44
	RETLW 0x45
	RETLW 0x4D
	RETLW 0x54
	RETLW 0x55
	RETLW 0x5B
	RETLW 0x12
	RETLW 0x58
	RETLW 0x1A
	RETLW 0x22
	RETLW 0x1B
	RETLW 0x21
	RETLW 0x23
	RETLW 0x2A
	RETLW 0x32
	RETLW 0x34
	RETLW 0x31
	RETLW 0x33
	RETLW 0x3A
	RETLW 0x3B
	RETLW 0x41
	RETLW 0x49
	RETLW 0x4B
	RETLW 0x4A
	RETLW 0x4C
	RETLW 0x52
	RETLW 0x59
	RETLW 0x0E
	RETLW 0x0D
	RETLW 0x15
	RETLW 0x1E
	RETLW 0x1D
	RETLW 0x26
	RETLW 0x24
	RETLW 0x2D
	RETLW 0x2E
	RETLW 0x2C
	RETLW 0x36
	RETLW 0x35
	RETLW 0x3D
	RETLW 0x3C
	RETLW 0x43
	RETLW 0x46
	RETLW 0x44
	RETLW 0x45
	RETLW 0x4D
	RETLW 0x54
	RETLW 0x55
	RETLW 0x5B
	RETLW 0x12
	RETLW 0x58
	RETLW 0x1A
	RETLW 0x22
	RETLW 0x1B
	RETLW 0x21
	RETLW 0x23
	RETLW 0x2A
	RETLW 0x32
	RETLW 0x34
	RETLW 0x31
	RETLW 0x33
	RETLW 0x3A
	RETLW 0x3B
	RETLW 0x41
	RETLW 0x49
	RETLW 0x4B
	RETLW 0x4A
	RETLW 0x4C
	RETLW 0x52
	RETLW 0x59
	RETLW 0x0E
	RETLW 0x0D
	RETLW 0x15
	RETLW 0x1E
	RETLW 0x1D
	RETLW 0x26
	RETLW 0x24
	RETLW 0x2D
	RETLW 0x2E
	RETLW 0x2C
	RETLW 0x36
	RETLW 0x35
	RETLW 0x3D
	RETLW 0x3C
	RETLW 0x43
	RETLW 0x46
	RETLW 0x44
	RETLW 0x45
	RETLW 0x4D
	RETLW 0x54
	RETLW 0x55
	RETLW 0x5B
	RETLW 0x12
	RETLW 0x58
	RETLW 0x1A
	RETLW 0x22
	RETLW 0x1B
	RETLW 0x21
	RETLW 0x23
	RETLW 0x2A
	RETLW 0x32
	RETLW 0x34
	RETLW 0x31
	RETLW 0x33
	RETLW 0x3A
	RETLW 0x3B
	RETLW 0x41
	RETLW 0x49
	RETLW 0x4B
	RETLW 0x4A
	RETLW 0x4C
	RETLW 0x52
	RETLW 0x59
	RETLW 0x0E
	RETLW 0x0D
	RETLW 0x15
	RETLW 0x1E
	RETLW 0x1D
	RETLW 0x26
	RETLW 0x24
	RETLW 0x2D
	RETLW 0x2E
	RETLW 0x2C
	RETLW 0x36
	RETLW 0x35
	RETLW 0x3D
	RETLW 0x3C
	RETLW 0x43
	RETLW 0x46
	RETLW 0x44
	RETLW 0x45
	RETLW 0x4D
	RETLW 0x54
	RETLW 0x55
	RETLW 0x5B
	RETLW 0x12
	RETLW 0x58
	RETLW 0x1A
	RETLW 0x22
	RETLW 0x1B
	RETLW 0x21
	RETLW 0x23
	RETLW 0x2A
	RETLW 0x32
	RETLW 0x34
	RETLW 0x31
	RETLW 0x33
	RETLW 0x3A
	RETLW 0x3B
	RETLW 0x41
	RETLW 0x49
	RETLW 0x4B
	RETLW 0x4A
	RETLW 0x4C
	RETLW 0x52
	RETLW 0x59
	RETLW 0x0E
	RETLW 0x0D
	RETLW 0x15
	RETLW 0x1E
	RETLW 0x1D
	RETLW 0x26
	RETLW 0x24
	RETLW 0x2D
	RETLW 0x2E
	RETLW 0x2C
	RETLW 0x36
	RETLW 0x35
	RETLW 0x3D
	RETLW 0x3C
	RETLW 0x43
	RETLW 0x46
	RETLW 0x44
	RETLW 0x45
	RETLW 0x4D
	RETLW 0x54
	RETLW 0x55
	RETLW 0x5B
	RETLW 0x12
	RETLW 0x58
	RETLW 0x1A
	RETLW 0x22
	RETLW 0x1B
	RETLW 0x21
	RETLW 0x23
	RETLW 0x2A
	RETLW 0x32
	RETLW 0x34
	RETLW 0x31
	RETLW 0x33
	RETLW 0x3A
	RETLW 0x3B
	RETLW 0x41
	RETLW 0x49
	RETLW 0x4B
	RETLW 0x4A


;------------------------------------------------------------------------------
; PLACE USER PROGRAM HERE
;------------------------------------------------------------------------------

          GOTO $

          END
 

facemanfacey

New Member
i think that the midi input is correct, i have wired the circuit exactly as the midi manufacturers association suggests as shown below:

(and please excuse the mistake on the original posts resistor values)

 
Last edited:
Status
Not open for further replies.

EE World Online Articles

Loading
Top