Hello!
I was not happy with the inability of my Whammy 4 to switch back and fourth trough the programs and got some inspiration from the original MIDI controller from Molten Voltage. I had an old 8051 kit collecting dust and decided to put a small prototype together. The basic function is implemented by three momentary switches - Up, Down and Active/Bypass mode. My biggest problem as usual was the de-bouncing code which can still be improved. The next step will be to move it from a breadboard to something more permanent. The source code file is available upon request.
(http://img230.imageshack.us/img230/4013/midi3.th.png) (http://img230.imageshack.us/i/midi3.png/)
Uploaded with ImageShack.us (http://imageshack.us)
(http://img338.imageshack.us/img338/2484/midicontroller004.th.jpg) (http://img338.imageshack.us/i/midicontroller004.jpg/)
Uploaded with ImageShack.us (http://imageshack.us)
(http://img593.imageshack.us/img593/5788/midicontroller003.th.jpg) (http://img593.imageshack.us/i/midicontroller003.jpg/)
Uploaded with ImageShack.us (http://imageshack.us)
;***************************************************************************
;* *
;* *
;* Digitech Whammy MIDI Control Program *
;* Version 0.7 *
;* 11/18/2010 *
;* *
;* *
;***************************************************************************
;
#INCLUDE "8051EQU.INC" ;include predefined constants
;
;
; VARIABLES AND CONSTANTS
;
; R5,R6,R7 - used in delay routines
; R4 - program value
; R1 - used for Program Change commands
; R0 - used for Program Change commands
;
; Ports
; P3
; P3.0 - Serial Receive
; P3.1 - Serial Transmit
; P1
; P1.0 - LED
; P1.1 - UP momentary switch (NC)
; P1.2 - DOWN momentary switch (NC)
; P1.3 - Active/Bypass momentary switch (NC)
;
; User Bits
; bit 20h - Active/Bypass Value
;**************************************************************************
;
; RESET ;reset routine
.ORG 0H ;locate routine at 00H
AJMP START ;jump to START
;
;**************************************************************************
;
; INTERRUPTS ;place interrupt routines at appropriate
; ;memory locations
.ORG 03H ;external interrupt 0
RETI
;
.ORG 0BH ;timer 0 interrupt
RETI
;
.ORG 13H ;external interrupt 1
RETI
;
.ORG 1BH ;timer 1 interrupt
RETI
;
.ORG 23H ;serial port interrupt
RETI
;
;*************************************************************************
;
.ORG 030H ;locate beginning of rest of program
;
;**************************************************************************
;
INITIALIZE: ;set up control registers
;
MOV PCON,#00H
MOV TMOD,#020H ;Set Timer 1 for Mode 2, Auto Reload
MOV TCON,#040H ;Turn timer 1 on
MOV PSW,#00H
MOV SCON,#050H ;set serial port to 8 bit UART
MOV TH1,#0FEH ;Reload value for timer 1 for 31.25k baud (24MHz xtal)
MOV P3,#003H ;Enable TxD and RxD
; MOV IE, #090H ;Enable Serial Interrupt
RET
;
;**************************************************************************
;
; Real code starts below.
;
;**************************************************************************
;**************************************************************************
;
DELAYMS: ;millisecond delay routine
; ;
MOV R7,#00H ;put value of 0 in register R7
LOOPA:
INC R7 ;increase R7 by one (R7 = R7 +1)
MOV A,R7 ;move value in R7 to Accumlator (also known as A)
CJNE A,#0FFH,LOOPA ;compare A to FF hex (256). If not equal go to LOOPA
RET ;return to the point that this routine was called from
;
;**************************************************************************
;
DELAYHS: ;half second delay above millisecond delay
; ;
MOV R6,#00H ;put 0 in register R6 (R6 = 0)
MOV R5,#002H ;put 2 in register R5 (R5 = 2)
LOOPB:
INC R6 ;increase R6 by one (R6 = R6 +1)
ACALL DELAYMS ;call the routine above. It will run and return to here.
MOV A,R6 ;move value in R6 to A
JNZ LOOPB ;if A is not 0, go to LOOPB
DEC R5 ;decrease R5 by one. (R5 = R5 -1)
MOV A,R5 ;move value in R5 to A
JNZ LOOPB ;if A is not 0 then go to LOOPB.
RET
;
;**************************************************************************
; Transmits the value in A through the serial (MIDI) port
SEND:
CLR TI
MOV SBUF,A
WAIT1:
JNB TI, WAIT1 ;Wait till done transmitting
RET
;**************************************************************************
;
; MIDI Functions
;
;**************************************************************************
;**************************************************************************
; Play Note Command
NOTE_ON:
MOV A,#090H ;NOTE ON Command
ACALL SEND
MOV A, R0 ;Play note specified by R0
ACALL SEND
MOV A, #40H ;Use attack velocity of 40H
ACALL SEND
RET
;**************************************************************************
; Note Off Command
NOTE_OFF:
MOV A,#080H ;NOTE OFF Command
ACALL SEND
MOV A, R1 ;Turn off note specified by R1
ACALL SEND
MOV A, #40H ;Use release velocity of 40H
ACALL SEND
RET
;**************************************************************************
; Program Change Command
PGM_CHG:
MOV A,#0C0H ;PROGRAM CHANGE Command
ACALL SEND
MOV A, R0 ;Program Change value specified by R0
ACALL SEND
RET
;**************************************************************************
; Blink the LED 3 times on boot
HELLO:
MOV R1,#0
HelloLoop:
CLR P1.0 ; turn LED on
ACALL DELAYHS
SETB P1.0 ; turn LED off
ACALL DELAYHS
INC R1
CJNE R1,#3,HelloLoop
RET
;**************************************************************************
;
; P1.0 - LED
; P1.1 - UP momentary switch (NC)
; P1.2 - DOWN momentary switch (NC)
; P1.3 - Active/Bypass momentary switch (NC)
; R4 - program value
; bit 20h - Active/Bypass Value
START: ;main program (on power up, program starts at this point)
MOV SP,#02FH ;Set Stack Pointer = 2FH
ACALL INITIALIZE ;set up control registers
ACALL HELLO ; Blink the LED 3 times on boot
CLR 20h ; set the default Active/Bypass mode to Active
MOV R4,#3 ; set the default program to 'Whammy Octave Up'
MOV A, R4
MOV R0, A
ACALL PGM_CHG ; set the initial program
SETB P1.1
SETB P1.2
SETB P1.3
SETB P1.0 ; Turn LED off
wait_for_pressed:
MOV C,P1.1
ORL C,P1.2
ORL C,P1.3
JNC wait_for_pressed
MOV R7,#255
deb_loop1:
MOV C,P1.1
ORL C,P1.2
ORL C,P1.3
JNC wait_for_pressed
DJNZ R7,deb_loop1
JB P1.1, inc_pgm
JB P1.2, dec_pgm
JB P1.3, act_bypass
SJMP pgm_change
act_bypass:
CPL 20h
SJMP pgm_change
inc_pgm:
INC R4
SJMP pgm_change
dec_pgm:
DEC R4
SJMP pgm_change
pgm_change:
MOV A, R4 ; Take care of values greater than 0-16
MOV B, #17
DIV AB
MOV A,B
JNB 20h,no_bypass ; Skip the next line for Active mode
ADD A, #17 ; Add 17 to the program number for Bypass mode
no_bypass:
MOV R0, A
ACALL PGM_CHG ; Set the program
CLR P1.0 ; Turn LED on
wait_for_release:
MOV C,P1.1
ORL C,P1.2
ORL C,P1.3
JC wait_for_release
MOV R7,#255
deb_loop2:
MOV C,P1.1
ORL C,P1.2
ORL C,P1.3
JC wait_for_release
DJNZ R7,deb_loop2
SETB P1.0 ; Turn LED off
AJMP wait_for_pressed
.END ;end of program
I managed to finish it this weekend. I decided to change the function of the middle button from on/off to max/min. This controls the virtual treadle position from 127 (when pressed) to 0 (on release). The next steps will be to implement a tap tempo button, step sequencer and probably to port to AVR ATTiny13.
(http://img818.imageshack.us/img818/8282/midicontroller012sm.jpg)
LiquidMetal, did you finish this priject? I want to make controller for WHAMY 4: up and down bank, that`s all i need:)
Yes, I finished it and it works very well. You will need to do a slight change to the program for just ups/downs. Let me know if you need further info.
Have anyone a contact information with topicstarter?