Buzby
Senior Member
Prompted by Chris' virtual buffer thread, and my recent acquisition of an AXE134 OLED, I decided to build a ( somewhat limited ) drum machine.
Most of the code is for the user interface.
Two buttons move the cursor to select the buffer position, and a third toggles the data at that point.
Holding a cursor key down for longer will extend or shorten the buffer, and a fourth button switches between 'Prog' and 'Run'.
In 'Run' mode the cursor keys adjust the tempo, and setting a tempo of zero causes the system to use an external clock.
The code is posted here really to show how a user interface can be built, not as an example of how to build a drum machine !.
Cheers,
Buzby
Code:
#picaxe 28X2
#no_data
#no_table
' Drum machine #1
symbol CurLftPin = pinC.0 ' Cursor left
symbol CurRgtPin = pinC.1 ' Cursor right
symbol TglDat = pinC.2 ' Toggle data, or set buffer length
symbol DelPin = pinC.3 ' Select mode
symbol ClkPin = pinC.4 ' Clock in
symbol OLEDpin = A.1
symbol OutPin = A.3 ' Data out pin
symbol pinsmem = b1 ' memory for pins
symbol oneshots = b2 ' oneshots for all pins in bits 16 to 23
symbol os_C0 = bit16 ' Oneshot from C.0
symbol os_C1 = bit17 ' Oneshot from C.1
symbol os_C2 = bit18 ' Oneshot from C.2
symbol os_C3 = bit19 ' Oneshot from C.3
symbol os_C4 = bit20 ' Oneshot from C.4
symbol os_C5 = bit21 ' Oneshot from C.5
symbol os_C6 = bit22 ' Oneshot from C.6
symbol os_C7 = bit23 ' Oneshot from C.7
symbol mode = bit24 ' mode flag, 0 = Prog, 1 = Run
symbol PushTimed = bit25 ' Left or right pressed for long time
symbol RunTimed = bit26 ' Run timer expired
symbol clockbit = bit27 ' Current clock, from internal or external
symbol BufLen = b4 ' Used to hold length of buffer
symbol BufEnd = b5 ' Used to hold address of last byte of buffer
symbol PushTimer = b6 ' Timer for long pushes
symbol RunTimer = b7 ' Timer for interal clock
symbol RunSpeedLim = b8 ' Setting for internal clock
symbol pincopies = b9 ' copy of full byte of port C
symbol disploop = b10
symbol temp1 = b11
symbol curpos = b12
symbol BufStart = 32 ' Buffer Start address
' ( )
#define OLEDbaud N2400_8
#define PushTimeLim 60
#define Prog 0
#define Runn 1
' Code starts here
' ----------------
pause 1000
serout OLEDpin, OLEDbaud, (254,1) : pause 30 ' Clear screen
serout OLEDpin, OLEDbaud, (254,130) ' line 1 pos 2
serout OLEDpin, OLEDbaud, ("Drum Machine #1")
serout OLEDpin, OLEDbaud, (254,192) ' line 2 pos 1
serout OLEDpin, OLEDbaud, ("--------------------")
serout OLEDpin, OLEDbaud, (254,148,"Prog")
serout OLEDpin, OLEDbaud, (254,14) ' Cursor ON
BufLen = 20 ' Buffer length ( Fixed at 20 at the moment )
BufEnd = BufStart + BufLen - 1 ' Calculate the end of the buffer
bptr = BufStart ' Set byte ptr to start of buffer
curpos = BufStart ' Set cursor same
RunSpeedLim = 25 ' Set initial run speed limit
temp1 = 192 - BufStart + curpos
serout OLEDpin, OLEDbaud, (254, temp1) ' Move cursor
do ' Main loop
' Make oneshots for all 8 pins of port C
' --------------------------------------
pincopies = pinsC ' Only read pin once, to avoid glitches
oneshots = pinsmem &/ pincopies ' Make one-shot
pinsmem = pincopies ' Update pin memory
' Make pin timer, detect long presses
'------------------------------------
if CurLftPin = 0 or CurRgtPin = 0 then
inc PushTimer
else
PushTimer = 0
endif
if PushTimer > PushTimeLim then
PushTimed = 1 ' Long press detected
PushTimer = 0
endif
' Mode selection
'---------------
if os_C3 = 1 then
Mode = not Mode
if mode = 0 then
serout OLEDpin, OLEDbaud, (254,148,"Prog ")
else
serout OLEDpin, OLEDbaud, (254,148,"Run ", #RunSpeedLim, " ")
endif
temp1 = 192 - BufStart + curpos
serout OLEDpin, OLEDbaud, (254, temp1) ' Restore cursor
PushTimed = 0 ' Reset long press detect when mode changes
PushTimer = 0
endif
' Programming mode
' ----------------
if mode = Prog then
' Cursor left
if os_C0 = 1 then
dec curpos ' Decrement cursor address
if curpos < BufStart then ' If before first byte ...
curpos = BufEnd ' ... reset cursor
endif
temp1 = 192 - BufStart + curpos
serout OLEDpin, OLEDbaud, (254, temp1) ' Move cursor
endif
' Cursor right
if os_C1 = 1 then
inc curpos ' Increment cursor address
if curpos > BufEnd then ' If after last byte ...
curpos = BufStart ' ... reset cursor
endif
temp1 = 192 - BufStart + curpos
serout OLEDpin, OLEDbaud, (254, temp1) ' Move cursor
endif
' Toggle memory
if os_C2 = 1 then
bptr = curpos
temp1 = not @bptr
@bptr = temp1
if temp1 > 0 then
serout OLEDpin, OLEDbaud, ("+")
else
serout OLEDpin, OLEDbaud, ("-")
endif
temp1 = 192 - BufStart + curpos
serout OLEDpin, OLEDbaud, (254, temp1) ' Restore cursor
endif
' Shrink buffer
if PushTimed = 1 and CurLftPin = 0 then
PushTimed = 0
BufEnd = BufEnd - 1 min BufStart
serout OLEDpin, OLEDbaud, (254,192) ' line 2 pos 1
serout OLEDpin, OLEDbaud, (" ")
for curpos = BufStart to BufEnd
bptr = curpos
temp1 = 192 - BufStart + curpos
serout OLEDpin, OLEDbaud, (254, temp1) ' Position cursor
if @bptr > 0 then
serout OLEDpin, OLEDbaud, ("+")
else
serout OLEDpin, OLEDbaud, ("-")
endif
next
curpos = BufStart
temp1 = 192 - BufStart + curpos
serout OLEDpin, OLEDbaud, (254, temp1) ' Restore cursor
endif
' Expand buffer
if PushTimed = 1 and CurRgtPin = 0 then
PushTimed = 0
BufEnd = BufEnd + 1 max 51
serout OLEDpin, OLEDbaud, (254,192) ' line 2 pos 1
serout OLEDpin, OLEDbaud, (" ")
for curpos = BufStart to BufEnd
bptr = curpos
temp1 = 192 - BufStart + curpos
serout OLEDpin, OLEDbaud, (254, temp1) ' Position cursor
if @bptr > 0 then
serout OLEDpin, OLEDbaud, ("+")
else
serout OLEDpin, OLEDbaud, ("-")
endif
next
curpos = BufEnd
temp1 = 192 - BufStart + curpos
serout OLEDpin, OLEDbaud, (254, temp1) ' Restore cursor
endif
endif ' end Prog mode
' Run mode
' --------
if mode = Runn then
' Go faster
if PushTimed = 1 and CurRgtPin = 0 then
PushTimed = 0
If RunSpeedLim > 0 then ' only try if not already at zero
RunSpeedLim = RunSpeedLim - 1 min 0 ' Reduce interval
serout OLEDpin, OLEDbaud, (254,148,"Run ", #RunSpeedLim, " ")
temp1 = 192 - BufStart + curpos
serout OLEDpin, OLEDbaud, (254, temp1) ' Restore cursor
endif
endif
' Go slower
if PushTimed = 1 and CurLftPin = 0 then
PushTimed = 0
RunSpeedLim = RunSpeedLim + 1 max 50 ' Increase interval
serout OLEDpin, OLEDbaud, (254,148,"Run ", #RunSpeedLim, " ")
temp1 = 192 - BufStart + curpos
serout OLEDpin, OLEDbaud, (254, temp1) ' Restore cursor
endif
' Update run timer
inc RunTimer
if RunTimer >= RunSpeedLim then ' Timer expired
RunTimer = 0 ' reset timer
RunTimed = 1 ' set timed bit, use to clock data out
endif
' use internal or external clock
if RunSpeedLim = 0 then
clockbit = os_C4 ' Use external clock
else
clockbit = RunTimed ' Use internal clock
RunTimed = 0
endif
' Clock data out
if clockbit = 1 then
inc curpos ' Increment cursor address
if curpos > BufEnd then ' If after last byte ...
curpos = BufStart ' ... reset cursor
endif
temp1 = 192 - BufStart + curpos
serout OLEDpin, OLEDbaud, (254, temp1) ' Move cursor
bptr = curpos
if @bptr > 0 then ' Output data from current bptr address,
pulsout OutPin, 500
endif
endif
endif ' end Runn mode
loop 'Main loop
Last edited: