Continue to Site

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.

  • 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.

MIDI Bit Bang Serial Routine Look Over

Status
Not open for further replies.

Jon Wilder

Active Member
I just wrote a bit bang serial routine for MIDI and was wondering if someone could look it over as this is my first time coding any sort of bit bang routine -

Code:
#define			RX		PORTB,1
#define			TX		PORTB,2


TX_REG			EQU		0x0C
RC_REG			EQU		0x0D
bitcounter		EQU		0x0E

;8 MHz crystal oscillator. Timer 0 set for prescaler of 1:32. TMR0 bit 0 is incremented every 16uS
;while TMR0 bit 1 is incremented every 32uS. TMR0 bit 2 is polled for baud rate of 31,250.
;Data is transmitted and received LSB first with 1 start bit and 1 stop bit.

;***********************************************************************************************************
;MIDI Transmit
;***********************************************************************************************************

TRANSMIT		movlw		0x08
			movwf		bitcounter	;set bit counter to count 8 bits to be transmitted
		
TX_start		btfss		INTCON,T0IF	;wait for timer to reset
			goto		TX_start
			bcf		TX		;send start bit
			
TX_bit			btfss		TX_REG,0	;see if bit 0 in TXREG is high or low
			goto		TX_low		;send low bit if low
			goto		TX_high		;send high bit if high

TX_low			btfss		TMR0,1		;wait for baud
			goto		TX_low
			bcf		TX		;send low bit
			goto		TX_shift
					
TX_high			btfss		TMR0,1		;wait for baud
			goto		TX_high
			bsf		TX		;send high bit
			goto		TX_shift

TX_shift		rrf		TX_REG,F	;shift bits in transmit register
			decfsz		bitcounter,F	;decriment bit counter, branch if 0
			goto		TX_bit
			goto		TX_stop		;proceed to send stop bit

TX_stop			btfss		TMR0,1		;wait for baud
			goto		TX_stop
			bsf		TX		;send stop bit
			return

;***********************************************************************************************************
;MIDI Receive
;***********************************************************************************************************

RECEIVE			movlw		0x08
			movwf		bitcounter	;set bit counter to count 8 bits to be recieved

RX_start		btfsc		RX		;wait for start bit rising edge
			goto		RX_start

			clrf		TMR0		;reset timer 0
			movlw		b'00000100'	;set timer 0 prescaler for 1:32
			option			
				
bitcenter		btfss		TMR0,0		;wait additional 16uS for bit center
			goto		bitcenter
			btfsc		RX		;recheck start bit, return if not start bit
			return

RX_bit			btfss		TMR0,1		;wait for baud
			goto		RX_bit

			btfss		RX		;see if bit on RX is high or low
			goto		RX_low		;receive low bit if low
			goto		RX_high		;receive high bit if high

RX_low			bcf		RC_REG,7	;set bit 7 in receive register
			goto		RX_shift

RX_high			bsf		RC_REG,7	;clear bit 7 in receive register
			goto		RX_shift

RX_shift		rrf		RC_REG,F	;shift bits in RCREG register
			decfsz		bitcounter,F	;decriment bit counter, branch if 0
			goto		RX_bit		;receive next bit
			goto		RX_stop		;receive stop bit

RX_stop			btfss		TMR0,1		;wait for baud
			goto		RX_stop

stop_w8			btfss		rx		;check for stop bit
			goto		frame_error	;return if stop bit received
			return

Any and all suggestions would be greatly appreciated.

EDIT: On an interesting note I tried simulating this in MPLAB and for some reason it will not skip the next instruction upon bit 1 of TMR0 being set at the "btfss TMR0,1" instruction. Does anyone know why this is?
 
Last edited:
hi Jon,
Whats the PIC type..?

Can I suggest that you drop the 'bit bang' expression thats in common use, for goodness knows why. ??? and substitute 'bit switching'.:confused:

I will run it thru Oshonsoft, let you know..:)
 
hi Jon,
Whats the PIC type..?

Can I suggest that you drop the 'bit bang' expression thats in common use, for goodness knows why. ??? and substitute 'bit switching'.:confused:

I will run it thru Oshonsoft, let you know..:)

Ah yes...it's for a 16F84 or any other type of 16F series PIC that doesn't have an on chip UART. I use the 16F628 so I don't really need it. I'm just merely writing the code in order to gain an understanding of 'bit switching'. ;)
 
Ah yes...it's for a 16F84 or any other type of 16F series PIC that doesn't have an on chip UART. I use the 16F628 so I don't really need it. I'm just merely writing the code in order to gain an understanding of 'bit switching'. ;)

hi Jon
A lot of coding errors, you are calling 'low' and 'high' and there is no low or high label....do you mean TX_ or RX low , high. ?
 
hi Jon
A lot of coding errors, you are calling 'low' and 'high' and there is no low or high label....do you mean TX_ or RX low , high. ?

Ah yes I just caught that. I changed the code to TX_low and TX_high.
 
Hi Jon,

If it helps, here are general purpose bit-banged TX and RX routines which rely on a general purpose fixed delay subsystem to provide precise "cycle accurate" bit timing with almost any clock (4, 8, 12, 16, or 20-MHz);

Code:
;
;   19200 baud ->  52.1 usec bit time
;   57600 baud ->  17.4 usec bit time
;  115200 baud ->   8.7 usec bit time
;
        radix   dec
clock   equ     8               ; clock, 4, 8, 12, 16, or 20 MHz
usecs   equ     clock/4         ; cycles/usec operand multiplier
;
bitTime equ     52*usecs        ; cycles per bit @ 19200 baud
;
Code:
Put232
        movwf   serbyte         ;                                 |B0
        movlw   10              ; 1 start + 8 data + 1 stop bit   |B0
        movwf   BitCtr          ; setup bit counter               |B0
        clrc                    ; C = 0 = start bit               |B0
        goto    SendBit         ; send start bit                  |B0
TxBit
        DelayCy(bitTime-10)     ; 52-usecs minus 10 cycles        |B0
        setc                    ; always shift in a 'stop' bit    |B0
        rrf     serbyte,F       ; put data bit in Carry           |B0
SendBit
        movf    PORTB,W         ; read port                       |B0
        iorlw   1<<TxPin        ; TxPin = 1                       |B0
        skpc                    ;                                 |B0
        xorlw   1<<TxPin        ; TxPin = 0                       |B0
        movwf   PORTB           ; precise "bitTime" intervals     |B0
        decfsz  BitCtr,F        ; done? yes, skip, else           |B0
        goto    TxBit           ; send next bit                   |B0
        return                  ;                                 |B0
;
Code:
Get232
        btfss   PORTB,RxPin     ; start bit (1)? yes, skip, else  |B0
        goto    Get232          ; loop (wait for start bit)       |B0
        DelayCy(bitTime/2)      ; delay 1/2 bit time              |B0
        movlw   8               ;                                 |B0
        movwf   BitCtr          ; BitCtr = 8                      |B0
RxBit
        DelayCy(bitTime-7)      ; precise 208-usec bit timing     |B0
        clrc                    ; assume '0'                      |B0
        btfss   PORTB,RxPin     ; a '0' bit? yes, skip, else      |B0
        setc                    ; set to '1'                      |B0
        rrf     serbyte,F       ; b0 first, b7 last               |B0
        decfsz  BitCtr,F        ; done? yes, skip, else           |B0
        goto    RxBit           ; get another bit                 |B0
        return                  ;                                 |B0
;
 
Last edited:
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top