Full Version : Vasilis AVR Attiny26 MIDI Generator (ASM)
avr >>SOUND & MUSIC PROJECTS >>Vasilis AVR Attiny26 MIDI Generator (ASM)


Admin3- 04-19-2006
MIDI generator

Control some MIDI device with ATtiny26. The code can be convert it for any AVR family microcontroller..

Designed by: Stergiopoulos Vasilis

Link: http://www.serasidis.gr/circuits/MidiGener...diGenerator.htm

This circuit based on ATtiny26 but it could be anyone microcontroller of AVR family. Produce stable one MIDI tone and you can change it by press some keys like to change midi channel 0-15 , velocity 0-127, pitch 0-127. It is start from center tone © at channel 0 with velocity 30. Every tone is equivalence with two midi events "note on" and "note off". A LED is used to show the start and stop of the midi tone. This LED is turn-on every time a command is executed by the key pressing.

CODE

; midi tester
; program by stergio33 (vster@tee.gr)
; this test circuit sends midi notes constantly, just to study the midi protocol
; there are some buttons connected that let you change the channel, pitch and velocity
; designed for ATtiny26. Program the fuse bits so that it runs at 4MHz internal oscilator

.NOLIST
.INCLUDE "tn26def.inc"
.LIST

; Used registers r16 = scratch, timer = r19(MSB), r18, r17
.def Rout  = r20; output register to be shifted for midi
.def Poa  = r21; state of output port A
.def cnt  = r22; general counter
.def key  = r23; 1-127 for midi messages
.def veloc  = r24; 1-127 velocity of note
.def channel = r25; 0-15 midi channel

.equ midi  = 0 ; midi output
.equ led  = 1 ; led output pin

.equ chanSelect  = 0; increase channel button
.equ VelocDecr  = 1; decrease velocity button
.equ VelocIncr  = 2; increase velocity button
.equ KeyInc   = 3; increase key button
.equ DeChannel  = 4; decrease channel
.equ KeyDec   = 5; decrease key button

; Code starts here
.CSEG
.ORG $0000

rjmp arxi

; **************** End of interrupt service routines ***********

; ****************** delay routines **************

delay: ldi  r19,8
 ldi  r18,255; delay routine
 ldi  r17,255
del1: dec  r17
 brne del1
 ser  r17
 dec  r18
 brne del1
 ser  r18
 dec  r19
 brne del1
 ret

sdel: ldi  r16,18; short delay at 4Mhz for internal oscilator
sdel1: dec  r16
 brne sdel1
 ret

; Rout = r20 output register to be shifted for midi
; Poa  = r21 output buffer for port A
; cnt  = r22 general counter
; sends a byte (stored in Rout) serially to midi output, starting from LSB
send: ldi  cnt,10
 com  Rout
 sec
send2: brcc send3
 cbi  portA,midi; midi out
 rjmp send4
send3: sbi  portA,midi
 nop
send4: rcall sdel
 rcall sdel
 lsr  Rout
 dec  cnt
 brne send2
 ret

; ****************** note on ************************************************
; key = r23  1-127 for midi messages
; veloc = r24 1-127 velocity of note
; channel = r24 0-15 midi channel
; send note on. 1st byte $9n (n=0-f), 2nd:key (0-$7f), 3rd:velocity (0-$7f)
; midi velocity = 31250 bits/sec, so for the duration of a bit is 1/31250 = 32us
noteOn: ldi  rout,$90; note-on message starts with 9
 rjmp note1
noteOf: ldi  rout,$80; note-off message starts with 8
note1: sbi  porta,led
 mov  r16,channel
 andi r16,$0f
 or  rout,r16
 rcall send
 rcall sdel
 mov  rout,key
 rcall send
 rcall sdel
 mov  rout,veloc
 rcall send
 rcall delay
 cbi  porta,led
 ret
; ************************************************************************
incKey: inc  key   ; increase key (pitch)
 andi key,127
 sbi  porta,led
 rcall delay
 cbi  porta,led
incKe1: ret
; ************************************************************************
decKey: tst  key   ; decrease key (pitch)
 breq decKe1
 dec  key
 sbi  porta,led
 rcall delay
 cbi  porta,led
decKe1: ret
; ************************************************************************
incVeL: ldi  r16,10  ; increase velocity
 add  veloc,r16
 andi veloc,127
 breq incve1
 sbi  porta,led
 rcall delay
 cbi  porta,led
incVe1: ret
; ************************************************************************
decVeL: ldi  veloc,3  ; decrease velocity
 sbi  porta,led
 rcall delay
 cbi  porta,led
 ret
; ************************************************************************
inChan: inc  channel  ; increase channel circular
 andi channel,15
 sbi  porta,led
 rcall delay
 cbi  porta,led
inCha1: ret
; ************************************************************************
deChan: tst  channel  ; decrease channel
 breq deCha1
 dec  channel
 sbi  porta,led
 rcall delay
 cbi  porta,led
deCha1: ret
; **************** End of the subroutines section ***************


; ******************** Main program ****************************

arxi: ldi  r16,RAMEND ; Initiate Stackpointer.
 out  SP,r16
 ldi  r16,255
 out  ddra,r16 ; porta is outputs
 clr  r16
 out  ddrb,r16 ; portb is inputs
 out  porta,r16
 ser  r16
 out  portb,r16 ; pull ups for portb

 clr  Poa
start: out  PortA,Poa
 ldi  channel,0
 ldi  key,$3c  ; start with middle C
 ldi  veloc,30
next: rcall noteOn
 rcall delay
 rcall noteOf
 rcall delay
 sbis pinB,VelocDecr; decrease velocity button pressed?
 rcall decVeL
 sbis pinB,VelocIncr; increase velocity button pressed?
 rcall IncVel
 sbis pinB,chanSelect; increase channel button pressed?
 rcall inChan
 sbis pinB,KeyInc ; icrease key button pressed?
 rcall incKey
 sbis pinB,KeyDec ; decrease key button pressed?
 rcall decKey
 sbis pinB,DeChannel; decrease channel button pressed?
 rcall deChan
 rjmp next





Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.