Upload
markus-flicke
View
91
Download
0
Embed Size (px)
Citation preview
C:\Users\M\Desktop\codeextracted\initialise.asm
.include "m128def.inc"
.include <macros.inc>
.ORG $0;;************************************************************************; Interrupt List Section;************************************************************************
jmp Init ; jmp is 2 word instruction to set correct vector
reti ; External 0 interrupt Vector nop ; Vector Addresses are 2 words apartreti ; External 1 interrupt Vector nop ; Vector Addresses are 2 words apartreti ; External 2 interrupt Vector nop ; Vector Addresses are 2 words apartreti ; External 3 interrupt Vector nop ; Vector Addresses are 2 words apartreti ; External 4 interrupt Vector nop ; Vector Addresses are 2 words apartreti ; External 5 interrupt Vector nop ; Vector Addresses are 2 words apartreti ; External 6 interrupt Vector nop ; Vector Addresses are 2 words apartreti ; External 7 interrupt Vector nop ; Vector Addresses are 2 words apartjmp OSC3_TRIG ; Timer 2 Compare Vector ;nop ; Vector Addresses are 2 words apartreti ; Timer 2 Overflow Vector nop ; Vector Addresses are 2 words apartreti ; Timer 1 Capture Vector nop ; Vector Addresses are 2 words apartjmp OSC2_TRIG ; Timer1 CompareA Vector ;nop ; Vector Addresses are 2 words apartreti ; Timer 1 CompareB Vector nop ; Vector Addresses are 2 words apartreti ; Timer 1 Overflow Vector nop ; Vector Addresses are 2 words apartjmp OSC1_TRIG ; Timer 0 Compare Vector ;nopreti ; Timer 0 Overflow interrupt Vector nop ; Vector Addresses are 2 words apartreti ; SPI Vector nop ; Vector Addresses are 2 words apartreti ; UART Receive Vector nop ; Vector Addresses are 2 words apartreti ; UDR Empty Vector nop ; Vector Addresses are 2 words apartreti ; UART Transmit Vector nop ; Vector Addresses are 2 words apartreti ; ADC Conversion Complete Vector nop ; Vector Addresses are 2 words apartreti ; EEPROM Ready Vector nop ; Vector Addresses are 2 words apartreti ; Analog Comparator Vector nopreti; Timer1 CompareC Handlernopreti ; Timer3 Capture Handlernopreti;jmp SEQ_TRIG; Timer3 CompareA Handlernopreti; Timer3 CompareB Handlernopreti; Timer3 CompareC Handlernopreti ; Timer3 Overflow Handlernop
; ** ATmega103(L) Assembly Language File - IAR Assembler Syntax **; ** Author : C. Foudas; ** Company : Imperial College, High Energy Physics division
Page: 1
C:\Users\M\Desktop\codeextracted\initialise.asm
; ** Comment : This is an example of using the LCD display;.DEVICE ATmega128
.def TempReg = r20 ;General register used for counting
.def varA = r21 ;variables inside subroutines
.def varB = r22
.def varC = r23
.def subout = r24 ;output from subroutines
.def parA = r25 ;input for subroutines
.def status = r12 ;used for keyboard flag, and note number
; |7 |6 |5 |4 |3 |2 |1 |0 |; status = |KEYB|Cpos|Cpos|Cpos|Cpos|Cpos|Cpos|Cpos| keyboard flag, 0 = nubmers, 1 = notes, Cpos = cursor (noteNumber) position (0-40)
;SRAM locations:.equ BeatSpeedAddress = 299 ;location of Beats Per Minute (BPM) storage.equ DefaultOctaveAddress = 298 ;Location of Default Values.equ DefaultVolumeAddress = 297.equ DefaultLengthAddress = 296
.equ TrackLengthAddress = 300 ;"editing" TrackLength
.equ FirstNoteAdress = 301 ;"editing" First Note
.equ ASaveTrackLengthAddress = 600 ;SaveA
.equ BSaveTrackLengthAddress = 900 ;SaveB
.equ CSaveTrackLengthAddress = 1200 ;SaveC
; SRAM STORAGE
;_______________________________________________________________________________;; -> PITCH, OCTAVE, # range(1-85) (inc octave 7);;_______________________________________________________________________________;;; -> Volume range(1-5);;______________________________________________________________________________
;; -> Length;;_______________________________________________________________________________
rjmp initInit:
; ************* Default Values *************ldi tempreg,120 ;Beat Clock Speedsts BeatSpeedAddress,tempreg
; ************* Stack Pointer Setup Code ldi r16, $0F ; Stack Pointer Setup to 0x0FFFout SPH,r16 ; Stack Pointer High Byte ldi r16, $FF ; Stack Pointer Setup out SPL,r16 ; Stack Pointer Low Byte
; ******* RAMPZ Setup Code **** lower memory page arithmeticldi r16, $00 ; 1 = EPLM acts on upper 64Kout RAMPZ, r16 ; 0 = EPLM acts on lower 64K
; ******* Sleep Mode And SRAM *******; ; tell it we want read and write activity on RE WRldi r16, $C0 ; Idle Mode - SE bit in MCUCR not setout MCUCR, r16 ; External SRAM Enable Wait State Enabled
; ******* Comparator Setup Code **** ldi r16,$80 ; Comparator Disabled, Input Capture Disabled
Page: 2
C:\Users\M\Desktop\codeextracted\initialise.asm
out ACSR, r16 ; Comparator Settings
;------------------------; Timer0 Setup Code;------------------------ ;ldi r16,$01 ; Timer 0 Setup out TCCR0,r16 ; Timer - PRESCALE TCK0 BY 1ldi r16,$FF ; load timer with n=255out TCNT0,r16 ; The counter will go offout OCR0, r16
;------------------------; Timer1 Setup Code;------------------------
ldi r16, 0b00000001out TCCR1A,r16ldi r16,$01 ; Timer 0 Setup out TCCR1B,r16 ; Timer - PRESCALE TCK0 BY 1ldi r16,$FF ; load timer with n=255out TCNT1L,r16 ; The counter will go offldi r16,$FF ; load timer with n=255out TCNT1H,r16 ; The counter will go offldi r16,$00ldi r17, $FFout OCR1AH,r16out OCR1AL,r17
;------------------------; Timer2 Setup Code;------------------------
ldi r16,$01 ; Timer 0 Setup out TCCR2,r16 ; Timer - PRESCALE TCK0 BY 1ldi r16,$FF ; load timer with n=255out TCNT2,r16 ; The counter will go offout OCR2,r16
;-----------------------; Timer 3 Setup Code;-----------------------
SetB ETIMSK,OCIE3A,r16;TCCR3A already setSetB TCCR3B,CS30,r16SetB TCCR3B,CS32,r16ldi r16,$FFStore OCR3AL,r16
;------------------------; Interrupts Setup Code;------------------------
; in (256 - n)*256*250 nsec
ldi r16, 0b10010010 ; Timer Interrupt Enables out TIMSK, r16 ; T0,T1,T2: Compare
;------------------------; Port Setup Code;------------------------
ldi r16, $FFout DDRD,r16out PORTD, r16
; ******* Port A Setup Code **** ldi r16, $FF ; Address AD7 to AD0out DDRA, r16 ; Port A Direction Registerldi r16, $00 ; Init value out PORTA, r16 ; Port A value
Page: 3
C:\Users\M\Desktop\codeextracted\initialise.asm
call ResetTrackDefaults;Initialise Track lengths
LDI YH,high(ASaveTrackLengthAddress)LDI YL,low(ASaveTrackLengthAddress)
ldi tempreg,1st Y,tempreg
LDI YH,high(BSaveTrackLengthAddress)LDI YL,low(BSaveTrackLengthAddress)
st Y,tempreg
LDI YH,high(CSaveTrackLengthAddress)LDI YL,low(CSaveTrackLengthAddress)st Y,tempreg
seijmp main
Page: 5
C:\Users\M\Desktop\codeextracted\main.asm
.include "initialise.asm"
;---------------------------------- LoadScreen ------------------------------main:call clrdis ;Clears the LCD (found in "LCD.asm")call WelcomePattern ;Displays SYNTH in large letters, hard coded in "DelayAndMisc.asm"call HelloSound ;Plays the triple oscillator for startup sounds. Hard coded in "Tracks.asm"clicall shiftandwait ;Shifts the display left and right, aborting when A is pressed. After some time gives user a hint to "hold A";---------------------------------- Main Function ------------------------------
call Beta ;calls the Menue Loop
rjmp main
Beta: ;Menue Loop: calls subfunctions depending on the outcome of the dialogues
call IndexDialogue ;Main Menue, displays the Menue and returns input according to Menuebtn (0-3)=(A-D)
cpi subout,0breq NoteTrackSelected ;case A is pressed -> NoteTrackcpi subout,1breq SettingsSelected ;case B is pressed -> Settingscpi subout,2breq PlayTrackSelected ;case C is pressed -> PlayTrackcpi subout,3breq SaveLoadSelected ;case D is pressed -> Save/Loadcall UnexpectedError
;---------------------------------------------------------- NoteTrackNoteTrackSelected:
call NoteTrackDialogue ;Input for a new Track is called. (function sits in Dialogues.asm)
jmp Beta;---------------------------------------------------------- SettingsSettingsSelected:
call SettingsDialogue ;calls Settings, waits for selection, returns with 0 or 1 for btn A or B
cpi subout,0breq BeatClockSelectedcpi subout,1breq SetDefaultsSelectedcall UnexpectedError
;>>>>>>>>>>>>>>>>> BeatclockBeatClockSelected:
call BeatClockDialogue ;runs The Beat Clock Dialogue found in Dialogues.asm
call BlinkingA ;waits until A is pressed to continue back to the main Menue
jmp Beta;>>>>>>>>>>>>>>>>> DefaultsSetDefaultsSelected:
call DefaultsDialogue ;Asks for Note type specific Default values. Has sub Dialogues shown in Dialogus.asm
jmp Beta
;---------------------------------------------------------- PlayTrackPlayTrackSelected:
call Displaytrack ;Displays Track stored in SRAM "editing" space. Address = "TrackLengthAddress" (Initialise.asm for exact value)
call MainSequenceFunction ;Plays the Notes from all three "save" spaces. Function located in "Sequencer.asm"
call waitbtnup ;"keypad.asm" function that waits until all btns are released
jmp Beta;---------------------------------------------------------- Save/LoadSaveLoadSelected:
call SaveLoadDialogue ;Save&Load Dialogue that sets up store&load from SRAM. returns 0 for save and 1 for load
cpi subout,0breq SaveSelected
Page: 1
C:\Users\M\Desktop\codeextracted\main.asm
cpi subout,1breq LoadSelectedcall UnexpectedError
SaveSelected:call SpaceDialogue ;asks user for which savespace to usecpi subout,0 ;interprets input according to what readMenuebtn re
turnsbreq SaveASelectedcpi subout,1breq SaveBSelectedcpi subout,2breq SaveCSelected
SaveASelected:ldi parA,0call SaveTrack ;saves the Track to the selected (parA) SRAM locati
onjmp Beta
SaveBSelected:ldi parA,1call SaveTrackjmp Beta
SaveCSelected:ldi parA,2call SaveTrackjmp Beta
LoadSelected:call SpaceDialogue ;asks for which loadspacecpi subout,0 ;interprets user inputbreq LoadASelectedcpi subout,1breq LoadBSelectedcpi subout,2breq LoadCSelected
LoadASelected:ldi parA,0call LoadTrack ;loads Track from selected load space into the "edi
ting" space. Address = "Tracklengthaddress"+jmp Beta
LoadBSelected:ldi parA,1call LoadTrackjmp Beta
LoadCSelected:ldi parA,2call JingleBells ;EASTER EGG!! Plays Jingle bells, which is hard cod
ed in "Tracks.asm"call JingleBellsjmp Beta
jmp Beta
.include "DelayAndMisc.asm" ;import all the subroutines from all the files
.include "Sequencer.asm"
.include "Dialogues.asm"
.include "Keypad.asm"
.include "SoundL.asm"
.include "Tracks.asm"
.include "LCD.asm"
Page: 2
C:\Users\M\Desktop\codeextracted\LCD.asm
;*************************** LCD ********************************;Volume Characters in Program MemoryVol5:.db 0b01110, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111Vol4:.db 0,0, 0b01110, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111Vol3:.db 0,0,0,0, 0b01110, 0b11111, 0b11111, 0b11111Vol2:.db 0,0,0,0,0,0, 0b01110, 0b11111Vol1:.db 0,0,0,0,0,0,0,0b01110
;Note Length Characters in Program Memorysemiquaver:.db 0b11110,0b10000,0b11110,0b10000,0b11100,0b11110,0b11110,0b01100
quaver:.db 0b11000,0b10100,0b10010,0b10000,0b11100,0b11110,0b11110,0b01100
crotchet:.db 0b10000,0b10000,0b10000,0b10000,0b11100,0b11110,0b11110,0b01100
minim:.db 0b10000,0b10000,0b10000,0b10000,0b11100,0b10010,0b10010,0b01100
semibreve:.db 0b00000,0b00000,0b00000,0b00000,0b01100,0b10010,0b10010,0b01100
;*************************** LCD Cursor ****************************csrreset: ;resets the cursor to pos 0ldi tempreg, 2sts $8000,tempreg ;Sends reset instruction to LCDcall busyLCD ;waits for LCD to settle downcall NoteNumberReset ;resets NoteNumber in status registerret
NoteNumberReset: ;resets NoteNumber in status registerldi tempreg, 0b10000000and status, tempregret
csrmoveright: ;moves cursor to the rightldi tempreg, 0b00010100sts $8000,tempregcall busyLCDret
csrmoveleft: ;moves cursor to the leftldi tempreg, 0b00010000sts $8000,tempregcall busyLCDret
csrset: ;moves cursor to an lcd position parA(0-80); slight complication: At pos 64, the next position is84call csradjustment ;adjustment due to the complicationsbr parA,128sts $8000,parA ;instructs LCD to move the cursor to parA call busyLCDret
csradjustment: ;Whenever cursor was set to pos 63 and is set to pos 64 it fails and sets to other positions instead. push tempreg ;Problem solved by setting to position 80 and above instead of 60 and aboveclnmov tempreg,parA ;now tempreg contains pos valuesubi tempreg,60 ;pos - 60brpl adjust ;case positive -> adjust by adding 24 to parA. Otherwise Exit
Page: 1
C:\Users\M\Desktop\codeextracted\LCD.asm
jmp adjustmentEndadjust:ldi tempreg,24add parA,tempregadjustmentEnd:pop tempregret
csrtopleft: ;function that moves to the vol part of the note, pointed to by status addresspush parAclr parAcall findnotepos ;returns NotePos into suboutldi tempreg,2mul subout,tempreg ;NotePos (note number) *2 because the Note square is two spaces longmov parA,r0call csrsetpop parAret
csrtopright: ;function that moves to the vol part of the note, pointed to by status addresspush parA ;see csrtopleft. It just adds 1 to move to the next positionclr parAcall findnoteposldi tempreg,2mul subout,tempregmov parA,r0inc parAcall csrsetpop parAret
csrbtmright: ;moves cursor to the bottom right position of the note squarecall findnotepos ;see csrtopleftldi tempreg,2mul subout,tempregmov parA,r0ldi subout,40add parA,suboutinc parAcall csrsetret
csrpitch: ;moves cursor to the bottom left of thh note squarecall findnotepos ;see csrtopleftldi tempreg,2mul subout,tempregmov parA,r0ldi subout,40add parA,suboutcall csrsetret
;*************************** LCD Custom Characters ****************************WriteLCDsgram: ;writes a byte (parA) to CgRAMsts $C000,parAcall busyLCDret
CharWriteLCDsgram: ;writes a whole chararcter that has been set up in PM by .db.... method. also Z pointer needs to be loaded with start addressldi varA,0CharWriteLCDsgramLoop:LPM parA, Z+ ;loads the byte from program memory as pointed to by Z. Increments Zcall WriteLCDsgram ;writes the character to CgRAMinc VarAcpi varA,8brne CharWriteLCDsgramLoop ;case all 8 lines have been written to -> Exit. Otherwise l
Page: 2
C:\Users\M\Desktop\codeextracted\LCD.asm
oopret
writehomochar: ;writes a homogenous character to CgRAMclr tempreg ;Same as CharWriteLCDsgram, but it doesn't reload from PMcall WriteLCDsgramcall busylcdinc tempregcpi tempreg,8brne writehomocharret
defineVolumeAndNoteLengthChars:push ZLpush ZH
ldi tempreg,$40sts $8000, tempregcall busyLCD
LDI ZL, LOW(2*Vol1)LDI ZH, HIGH(2*Vol1)call CharWriteLCDsgram
LDI ZL, LOW(2*Vol2)LDI ZH, HIGH(2*Vol2)call CharWriteLCDsgram
LDI ZL, LOW(2*Vol3)LDI ZH, HIGH(2*Vol3)call CharWriteLCDsgram
LDI ZL, LOW(2*Vol4)LDI ZH, HIGH(2*Vol4)call CharWriteLCDsgram
LDI ZL, LOW(2*Vol5)LDI ZH, HIGH(2*Vol5)call CharWriteLCDsgram
LDI ZL, LOW(2*semiquaver)LDI ZH, HIGH(2*semiquaver)call CharWriteLCDsgram
LDI ZL, LOW(2*quaver)LDI ZH, HIGH(2*quaver)call CharWriteLCDsgram
LDI ZL, LOW(2*crotchet)LDI ZH, HIGH(2*crotchet)call CharWriteLCDsgram
pop ZHpop ZLret
shiftandwait: ;Shifts the display left and right, aborting when A is pressed. After some time gives user a hint to "hold A"ldi varA,4
shiftandwaitLoop: ;Loops after every shift left, shift right -> loopldi tempreg,0b11011sts $8000,tempreg ;shift command to LCDcall busylcdcall readbtndel ;delays and reads btns in the meantime. setting subout in case they are pressedcall readbtndel
ldi tempreg,0b11111sts $8000,tempreg ;shift command to LCDcall busylcdcall readbtndel
Page: 3
C:\Users\M\Desktop\codeextracted\LCD.asm
call readbtndel ;delay and read
dec varAcpi varA,0breq SAWLTimeElapsed ;Case varA = 0 (i.e. it has cycled 4 times) -> Move on. Otherwise Loop
cpi subout, 0b11100001brne shiftandwaitLoop ;Case ä was pressed -> Exit. Otherwise Looprjmp shiftandwaitEnd
SAWLTimeElapsed: ;gets called after 4 cycles of shiftingcall bigdelcall GiveHint ;displays the hint that "Hold A to continue"call BlinkingA ;>A blinks in the bottom right until "A" button is pressed
shiftandwaitEnd:call waitbtnup ;wait for button releaseret
Hint: ;store Hint string in PM.db "Hold A to continue",0
GiveHint: ;prints the Hintldi parA, 20call csrsetLDI ZL, LOW(2*Hint) ;set Z pointer to string locationLDI ZH, HIGH(2*Hint)
printlcdHint: ;same as printlcd, but with a delay for estetic purposesLPM tempreg , Z+ ;loads first byte from PM. increments Zcpi tempreg, $00
BREQ MessEndHint ;case stringbyte = 0 -> Exit sts $C000, tempreg ;write stringbyte rcall busyLCD
call Del49ms ;delay for the looks rjmp printlcdHint ;loopMessEndHint: ret
;*************************** Setup & General ********************************
printlcd: ;prints a message on the LCD. Z needs to point to the start and a 0 must be included at the end of the message LPM tempreg , Z+ ;loads first byte from PM. increments Z
cpi tempreg, $00 ;case stringbyte = 0 -> Exit BREQ MessEnd sts $C000, tempreg;write stringbyte rcall busyLCD rjmp printlcd ;loopMessEnd: ret
busyLCD: ;waits for lcd to finish processing informationpush tempreg
busyLCDloop: lds tempreg, $8000 ;loads LCD status
sbrc tempreg, 7 ;check busy bit 7rjmp busyLCDlooppop tempreg
ret ;return if clear
clrdis: ldi tempreg,$01 ; Clear Display and send cursor to the most left po
sitionsts $8000,tempreg rcall busyLCD
ret
Initdisp:CALL DEL15ms ldi tempreg, $30 sts $8000,tempreg CALL DEL4P1ms
Page: 4
C:\Users\M\Desktop\codeextracted\Keypad.asm
;*************************** Keypad ********************************
;*************************** Keystrokes ********************************readbtn: ;returns in subout the btn pressed. If no btn is pressed, returns 0. BTN values are in accordance with the LCD character table. http://www.imperial.ac.uk/media/imperial-college/faculty-of-natural-sciences/department-of-physics/ug-labs/year-3/microprocessors/documentation/Liquid-Crystal-Display-Manual.PDF
push varApush varBpush tempregpush parAclr suboutrcall CheckRow ;gets input from port E and returns a pattern of Row in
put like: 0b0000rrrrrcall CheckCol ;gets col input like 0bcccc0000or varA,varB ;combine row and col in varA. Now it is 0bccccrrrrcom varAmov parA, varA ;moving varA into the general parameter register parAsbrc status,7 ;case highest bit in status register is set -> Input is
converted into a note valuecall noteconvertLCDsbrs status,7 ;case highest bit in status is cleared -> Input is conv
erted into a number valuecall nmbrconvertLCDpop parApop tempregpop varBpop varA
ret
readbtndel: ;reads the buttons for a short time. Used Whenever a delay and input is required at the same time
LDI XH, HIGH(13000) ;set up a big number in XLDI XL, LOW (13000)
readbtndelloop:call readbtn ;read from the buttons and put result into suboutSBIW XL, 1 ;decrement X, returns "equal" state if X = 0brne readbtndelloop ;case X > 0 -> Loop again
ret
waitreadbtn: ;waits for input and returns btn pressed iff input has occurred
call readbtn ;reads input and returns 0 if no inputcpi subout,0breq waitreadbtn ;case subout = 0 (no input) -> Loopcall waitbtnup ;Wait for btn release (to avaoid triggering the next "r
eadbtn" program steps, as processor is faster than fingers)ret
waitbtnup: ;continues the script iff no btn is pressedpush subout
waitbtnupinit:call readbtn ;returns 0 if no btn is pressedcpi subout,0brne waitbtnupinit ;case subout not 0 -> Loopcall DEL15mscall readbtncpi subout,0 ;check a second time (to avoid bouncing of btn)brne waitbtnupinitcall DEL15mscall readbtncpi subout,0 ;check a third time (to avoid bouncing of btn)brne waitbtnupinitpop suboutret
waitbtndown: ;waits until a certain btn(parA) has been pressedmov varA,parA ;makes parA a local variable to the function (i.e. parA
may be changed in other subroutines)call waitreadbtncp varA,suboutbrne waitbtndown
ret
Page: 1
C:\Users\M\Desktop\codeextracted\Keypad.asm
waitbtnpressed: ;waits until a certain btn(parA) has been pressedmov varA,parA ;makes parA a local variable to the function
waitbtnpressedinit:call waitreadbtn ;waits until any button has been pressed and reads itcp varA,suboutbrne waitbtnpressedinit ;case btn pressed = parA -> continue, Otherwise Loopcall waitbtnup ;wait for btn release
ret
KeyA: ;waits for key A to be pressed and releasedpush parA ;A is used as the "continue" keyldi parA,0b11100001call waitbtnpressedpop parA
ret
BlinkingA: ;displays >A in btm right corner and blinks. Returns when A was pressed
ldi parA,78call csrset ;goes to position 78ldi parA,0b111110call showlcd ;show "<"ldi parA,65call showlcd ;show "A"call readbtndel ;Waits and reads in the meantime. Majority of time spen
t in this loop is hereldi parA,78 ;goes to position 78call csrsetldi parA,0b100000call showlcd ;writes empty char to delete the patterncall showlcdcall readbtndel ;Waits and reads againcpi subout,0b11100001 ;Checks if any of the BTN functions have returned subou
t = ä (the Next key)brne BlinkingA ;case not ä pressed -> Loop, Otherwise Exitcall waitbtnup
ret
ReadMenueBtn: ;Reads btn (A-D) and returns (0-3). Requires parA = Number of buttons to check
mov varA,parA ;Make parA Local variablecall waitreadbtn ;Wait until Input occurscpi subout, 0b11100001breq ReadMenueBtnOutputA ;case subout = ä -> OutputAdec varA ;decrement varA. Count downcpi varA,0breq ReadMenueBtnOutOfRange ;case varA = 0 -> Input out of Range (otherwise
dec varA can lead to 0 -> 255 ->254 ->253 with unknown errorscpi subout,66breq ReadMenueBtnOutputB ;case subout = B -> return Bdec varAcpi varA,0breq ReadMenueBtnOutOfRange ;check out of rangecpi subout,67breq ReadMenueBtnOutputC ;case subout = B -> return Cdec varAcpi varA,0breq ReadMenueBtnOutOfRange ;check out of rangecpi subout,0b11110010breq ReadMenueBtnOutputD ;case subout = D -> return D
ReadMenueBtnOutOfRange:call OutOfRangePrompt ;In case BTN out of range -> Show the out of ra
nge prompt in "dialogues.asm"call keyA ;wait for next key (A) has been pressed and rel
easedcall clrdis ;clear displayrjmp ReadMenueBtn ;go back to reading the menue btn
ReadMenueBtnOutputA:ldi subout,0rjmp ReadMenueBtnEnd
Page: 2
C:\Users\M\Desktop\codeextracted\Keypad.asm
ReadMenueBtnOutputB:ldi subout,1rjmp ReadMenueBtnEnd
ReadMenueBtnOutputC:ldi subout,2rjmp ReadMenueBtnEnd
ReadMenueBtnOutputD:ldi subout,3rjmp ReadMenueBtnEnd
ReadMenueBtnEnd:ret;*************************** Raw Input ********************************
CheckRow: ;Checks portE for the row information of Keys pressedldi TempReg,$0F ;sets Port Registers so inputs have pull up Rsout PORTE,TempRegldi TempReg,$F0 ;setting low bits as INPUTS, hi bits as OUTsout DDRE,TempRegnop nop nop nop nop nop nop nop nop nopin varA,PINE ;stores row Information in varA low bits. Pattern like
0000xxxx. i.e. 0b00001101ret
CheckCol: ;Checks portE for Columnldi TempReg,$F0 ;sets Port Registersout PORTE,TempRegldi TempReg,$0F ;sets highest 4 bits as inputout DDRE,TempRegnop nop nop nop nop nop nop nop nop nopin varB,PINE ;stores column information as xxxx0000 e.g. 0b10010000ret
;*************************** Convert into ASCII ********************************nmbrconvertLCD:;converting the row/column pattern into lcd displayable code. lookup on page 18 of: http://www.imperial.ac.uk/media/imperial-college/faculty-of-natural-sciences/department-of-physics/ug-labs/year-3/microprocessors/documentation/Liquid-Crystal-Display-Manual.PDF;to convert the numbers into binary, subtract 00110000 = 48
ldi TempReg,0b00010001 ;case ccccrrrr = 0b00010001cpse parA,TempRegcpse parA,parAldi subout,49 ;then for LCD code subout = 49 (1 in decimal)
ldi TempReg,18 ;case = 00010010cpse parA,TempRegcpse parA,parAldi subout,50 ;=2
ldi TempReg,20 ;case = 00010100cpse parA,TempRegcpse parA,parAldi subout,51 ;=3
ldi TempReg,24 ;case = 00011000cpse parA,TempRegcpse parA,parAldi subout,0b11100001 ;=ä (Was chosen for the "continue key A" on the keyboar
d. A is already being used in NoteConvert for note A.
ldi TempReg,33 ;00100001cpse parA,TempRegcpse parA,parAldi subout,52 ;=4
ldi TempReg,34 ;00100010cpse parA,TempRegcpse parA,parAldi subout,53 ;=5
ldi TempReg,36 ;00100100cpse parA,TempRegcpse parA,parA
Page: 3
C:\Users\M\Desktop\codeextracted\Keypad.asm
ldi subout,54 ;=6
ldi TempReg,40 ;00101000cpse parA,TempRegcpse parA,parAldi subout,66 ;=B
ldi TempReg,65 ;01000001cpse parA,TempRegcpse parA,parAldi subout,55 ;=7
ldi TempReg,66 ;01000010cpse parA,TempRegcpse parA,parAldi subout,56 ;=8
ldi TempReg,68 ;01000100cpse parA,TempRegcpse parA,parAldi subout,57 ;=9
ldi TempReg,72 ;01001000cpse parA,TempRegcpse parA,parAldi subout,67 ;=C
ldi TempReg,129 ;10000001 cpse parA,TempRegcpse parA,parAldi subout,42 ;=*
ldi TempReg,130 ;10000010cpse parA,TempRegcpse parA,parAldi subout,48 ;=0
ldi TempReg,132 ;10000010cpse parA,TempRegcpse parA,parAldi subout,35 ;=#
ldi TempReg,136 ;10000100 cpse parA,TempRegcpse parA,parAldi subout,0b11110010 ;Exit btn. Greek letter (I think its theta), D is alrea
dy used in noteconvert
ret
noteconvertLCD: ;very similar to NMBRconvertLCD, but it uses Letter outputs for 1-6 (to enter pitch in NoteTrackDialogue[Dialogues.asm])
ldi TempReg,0b00010001cpse parA,TempRegcpse parA,parAldi subout,0b01000011 ;C
ldi TempReg,18cpse parA,TempRegcpse parA,parAldi subout,0b01000100 ;D
ldi TempReg,20cpse parA,TempRegcpse parA,parAldi subout,0b01000101 ;E
ldi TempReg,24cpse parA,TempRegcpse parA,parAldi subout,0b11100001 ;=ä continue char
ldi TempReg,33
Page: 4
C:\Users\M\Desktop\codeextracted\Keypad.asm
cpse parA,TempRegcpse parA,parAldi subout,0b01000110 ;F
ldi TempReg,34cpse parA,TempRegcpse parA,parAldi subout,0b01000111 ;G
ldi TempReg,36cpse parA,TempRegcpse parA,parAldi subout,0b01000001 ;A
ldi TempReg,40cpse parA,TempRegcpse parA,parAldi subout,0b01000010 ;B
ldi TempReg,65cpse parA,TempRegcpse parA,parAldi subout,55
ldi TempReg,66 ;8cpse parA,TempRegcpse parA,parAldi subout,56
ldi TempReg,68 ;9cpse parA,TempRegcpse parA,parAldi subout,57
ldi TempReg,72 ;Ccpse parA,TempRegcpse parA,parAldi subout,67
ldi TempReg,129 ;10000001 *cpse parA,TempRegcpse parA,parAldi subout,42
ldi TempReg,130 ;0cpse parA,TempRegcpse parA,parAldi subout,48
ldi TempReg,132 ;#cpse parA,TempRegcpse parA,parAldi subout,35
ldi TempReg,136 ;Exit BTN, weird 0 with bar in middle/ D was already takencpse parA,TempRegcpse parA,parAldi subout,0b11110010ret
Page: 5
C:\Users\M\Desktop\codeextracted\Dialogues.asm
;*************************** Dialogues ****************************;*************************** General ****************************CaptureThreeDigits: ;captures a 3 digit decimal number
mov tempreg,statuscbr tempreg,128mov status,tempreg ;Set Number input flag in Statuscall clrdis ;clear displaypush varA ;100spush varB ;10spush varC ;1s
call waitreadbtn ;wait and read btnmov varA,subout ;save 100smov parA,varAcall showlcd ;shows the character that was put in
call waitreadbtn ;wait and read btnmov varB,subout ;save 10smov parA,varBcall showlcd ;displays the input corresponding to the button pressed
call waitreadbtn ;wait and read btncpi subout,0b11100001breq skiplastdigit ;case subout = ä -> i.e. no 100s digit will be entered -> s
kip 100s digit collection. (however this method results in a second ä press required)mov varC,suboutmov parA,varCcall showlcd ;show 1s digit entered
skiplastdigitreturn:
subi varA,48 ;subtract 0b00110000 to get computable numberssubi varB,48subi varC,48
mov XL,varA ;multiply first digit with 100ldi XH,100mul XL,XHmov varA,r0 ;store the result
mov XL,varB ;multiply second digit with 10ldi XH,10mul XL,XH
add varA,r0 ;add the 10s to the 100sbrcs outofrange ;case carry set -> value out of range. (i.e. cannot take nu
mbers above 255)add varA,varC ;add the 1s to the resultbrcs outofrange ;if carry bit is set = the input is out of range
rjmp CTDFinal ;skip all the branches to the end of function
outofrange: ;discovered that if the addition is too big for the carry (i.e. sum>256*2) then the program just breaks
call clrdiscall busyLCDcall OutofrangePromptcall keyA
rjmp capturethreedigits
Skiplastdigit: ;A 2digit decimaly has been entered. We need to move 100s -> 10s and 10s->1s
mov varC,varB ;copy first and second entered digit into varB and varC respectively
mov varB,varAcall clrdis ;adjusting display for 2digit inputcall busyLCDmov parA,varBcall showlcd ;show new 10smov parA,varCcall showlcd ;show new 1s
rjmp skiplastdigitreturn
CTDFinal:
Page: 1
C:\Users\M\Desktop\codeextracted\Dialogues.asm
mov subout,varA ;pass on the digits as subout (convention)pop varCpop varBpop varA
ret
;-------------------------- Settings --------------------------SettingsDialogue: ;Chooses between Set BeatClock and Set Defaultscall SettingsPattern ;Displays the Promptldi parA,2call ReadMenueBtn ;Reads the Menue Buttons for input (2buttons)ret
ShowCurrentBeatClock: ;Displays the current Beat clock value as "(NNN)" N=number
ldi parA,0b00101000call showlcd ;write "("
ldi YH,high(BeatSpeedAddress) ;Set up Y for the SRAM location of where BPM information is stored
ldi YL,low(BeatSpeedAddress)
LD subout,Y ;load the BPM(beats per minute) from SRAM
mov parA,suboutcall ConvertToDecimalDigits ;convert BPM to Decimal digits (for individual
display)ldi tempreg,48mov parA,varAadd parA,tempreg ;convert decimal number into LCD table numbercall showlcd ;write 100s digitmov parA,varBadd parA,tempregcall showlcd ;write 10s digitmov parA,varCadd parA,tempregcall showlcd ;write 1s digit
ldi parA,0b00101001call showlcd ;write ")"
ret
SettingsPattern: ;shows the Settings promptcall clrdiscall FirstSettingsRow ;shows BeatClock with (NNN) current beat clock informationldi parA,20call csrsetcall ThirdSettingsRow ;shows the set Defaults promptret
FirstSettingsRowA: ;Set up Beat Clock text in PM.db "A. Beat Clock",0FirstSettingsRow: ;display Beat Clock text
LDI ZL, LOW(2*FirstSettingsRowA) ;set Z pointer to PM addressLDI ZH, HIGH(2*FirstSettingsRowA)call printlcd ;use Zpointer to print textcall ShowCurrentBeatClock ;display (NNN) the current beat clock value
ret
ThirdSettingsRowA: ;Set up Default prompt in the smae way.db "B. Def: Oct,Vol,Len",0ThirdSettingsRow:
LDI ZL, LOW(2*ThirdSettingsRowA)LDI ZH, HIGH(2*ThirdSettingsRowA)call printlcd
ret
;-------------------------- SetDefaults --------------------------DefaultsDialogue: ;Sets Octave,Volume and Notelength Devfault val
Page: 2
C:\Users\M\Desktop\codeextracted\Dialogues.asm
ues for ease of input in NoteTrackcall setdefaultspattern ;Displays the menueldi parA,4call ReadmenueBTN ;reads from 4 Menue btns A-D
cpi subout,0breq SetDefaultOctaveSelected ;case subout = 0 -> set Default Octavecpi subout,1breq SetDefaultVolumeSelected ;case subout = 1 -> set Default Volumecpi subout,2breq SetDefaultLengthSelected ;case subout = 2 -> set Default NoteLengthcpi subout,3breq ResetTrackDefaultsSelected ;case subout = 3 -> reset initial Defaults (fun
ction found in "DelayAndMisc.asm"
SetDefaultOctaveSelected: ;sets Default Octavecall SetDefaultOctavecall keyA ;waits for "Next" to be pressedjmp DefaultsDialogueEnd
SetDefaultVolumeSelected: ;set Default Volumecall SetDefaultVolumecall keyAjmp DefaultsDialogueEnd
SetDefaultLengthSelected: ;sets Default Note Lengthcall SetDefaultLengthcall keyAjmp DefaultsDialogueEnd
ResetTrackDefaultsSelected: ;resets all Defaults to initialcall ResetTrackDefaultsjmp DefaultsDialogueEnd
DefaultsDialogueEnd:jmp Beta ;goes back to the main menueret
SetDefaultOctave: ;Stores a new default octave in the respective SRAM location
call clrdis ;clear display mov tempreg,statuscbr tempreg,128mov status,tempreg ;set Input to read numberscall waitreadbtn ;wait and read buttonmov parA,suboutcall showlcd ;write the input number on LCDsubi subout,48ldi YL,low(DefaultOctaveAddress) ;Set Y pointer to Octave Addressldi YH,high(DefaultOctaveAddress)st Y,subout ;Save Octave
retSetDefaultVolume: ;same is octave
call clrdismov tempreg,statuscbr tempreg,128mov status,tempregcall waitreadbtnmov parA,suboutcall showlcdsubi subout,48ldi YL,low(DefaultVolumeAddress)ldi YH,high(DefaultVolumeAddress)st Y,subout
retSetDefaultLength: ;same as octave
call clrdismov tempreg,statuscbr tempreg,128mov status,tempregcall waitreadbtnmov parA,suboutcall showlcdsubi subout,48ldi YL,low(DefaultLengthAddress)
Page: 3
C:\Users\M\Desktop\codeextracted\Dialogues.asm
ldi YH,high(DefaultLengthAddress)st Y,subout
ret
SetDefaultsPattern: ;Writes the Prompt for the Defaults Dialogue. Works the same as every other "Set...Pattern" method above.
call clrdiscall FirstDefaultsRowldi parA,40call csrsetcall SecondDefaultsRowldi parA,20call csrsetcall ThirdDefaultsRowldi parA,60call csrsetcall FourthDefaultsRow
ret
FirstDefaultsRowA:.db "A. Octave",0FirstDefaultsRow:
LDI ZL, LOW(2*FirstDefaultsRowA)LDI ZH, HIGH(2*FirstDefaultsRowA)call printlcd
ret
SecondDefaultsRowA:.db "B. Volume",0SecondDefaultsRow:
LDI ZL, LOW(2*SecondDefaultsRowA)LDI ZH, HIGH(2*SecondDefaultsRowA)call printlcd
ret
ThirdDefaultsRowA:.db "C. NoteLength",0ThirdDefaultsRow:
LDI ZL, LOW(2*ThirdDefaultsRowA)LDI ZH, HIGH(2*ThirdDefaultsRowA)call printlcd
retFourthDefaultsRowA:.db "D. Set Input All",0FourthDefaultsRow:
LDI ZL, LOW(2*FourthDefaultsRowA)LDI ZH, HIGH(2*FourthDefaultsRowA)call printlcd
ret
;-------------------------- Save/Load --------------------------
SpaceDialogue: ;Menue for choosing which storage to load/savecall SpaceDialoguePattern ;shows the savespace prompt: SpaceA,SpaceB,SpaceCldi parA,3call ReadMenueBtn ;reads from 3 menue buttons
ret
SpaceDialoguePattern: ;Prompt is create in the same way as abovecall clrdiscall SpacePromptldi parA,40call csrsetcall SpacePromptAldi parA,20call csrsetcall SpacePromptBldi parA,60call csrsetcall SpacePromptC
ret
Page: 4
C:\Users\M\Desktop\codeextracted\Dialogues.asm
SaveLoadDialogue: ;User can make choice between Saving or Loadingcall SaveLoadDialoguePattern ;Shows the save/load Promptcall waitreadbtn ;wait and read until a button is pressedcpi subout, 0b11100001breq SLCoutA ;case subout = ä -> return 0cpi subout, 66breq SLCoutBcall OutOfRangePrompt ;case subout = B -> return 1call keyAjmp SaveLoadDialogue
SLCoutA:ldi subout,0rjmp SaveLoadDialogueEnd
SLCoutB:ldi subout,1rjmp SaveLoadDialogueEnd
SaveLoadDialogueEnd:ret
SaveLoadDialoguePattern: ;same as with e.g. the octave pattern. It creates a prompt
call clrdiscall SavePromptRowldi parA,20call csrsetcall LoadPromptRow
retSpacePromptG:.db "Select Storage Space:",0SpacePrompt:
LDI ZL, LOW(2*SpacePromptG)LDI ZH, HIGH(2*SpacePromptG)call printlcd
ret
SpacePromptF:.db "A Space A",0SpacePromptA:
LDI ZL, LOW(2*SpacePromptF)LDI ZH, HIGH(2*SpacePromptF)call printlcd
retSpacePromptBA:.db "B Space B",0SpacePromptB:
LDI ZL, LOW(2*SpacePromptBA)LDI ZH, HIGH(2*SpacePromptBA)call printlcd
retSpacePromptCA:.db "C Space C",0SpacePromptC:
LDI ZL, LOW(2*SpacePromptCA)LDI ZH, HIGH(2*SpacePromptCA)call printlcd
ret
SavePromptRowA:.db "A. Save",0SavePromptRow:
LDI ZL, LOW(2*SavePromptRowA)LDI ZH, HIGH(2*SavePromptRowA)call printlcd
ret
LoadPromptRowA:.db "B. Load",0LoadPromptRow:
LDI ZL, LOW(2*LoadPromptRowA)LDI ZH, HIGH(2*LoadPromptRowA)call printlcd
Page: 5
C:\Users\M\Desktop\codeextracted\Dialogues.asm
ret;-------------------------- Index --------------------------IndexDialogue: ;Main Menue. Makes a choice between "Create Track", "Settings", "Play Track" and "Save/ Load"
call IndexPatternldi parA,4call ReadMenueBtn ;returns 0 for A,1 for B,2 for C,3 for D
ret
IndexPattern: ;same pattern/prompt method as in e.g. "Octave" further up call clrdiscall FirstIndexRowldi parA,40call csrsetcall SecondIndexRowldi parA,20call csrsetcall ThirdIndexRowldi parA,60call csrsetcall FourthIndexRowret
FirstIndexRowA:.db "A. Create Track",0
FirstIndexRow:LDI ZL, LOW(2*FirstIndexRowA)LDI ZH, HIGH(2*FirstIndexRowA)call printlcd
ret
SecondIndexRowA:.db "B. Settings",0SecondIndexRow:
LDI ZL, LOW(2*SecondIndexRowA)LDI ZH, HIGH(2*SecondIndexRowA)call printlcd
ret
ThirdIndexRowA:.db "C. Play Track",0ThirdIndexRow:
LDI ZL, LOW(2*ThirdIndexRowA)LDI ZH, HIGH(2*ThirdIndexRowA)call printlcd
ret
FourthIndexRowA:.db "D. Save/Load",0FourthIndexRow:
LDI ZL, LOW(2*FourthIndexRowA)LDI ZH, HIGH(2*FourthIndexRowA)call printlcd
ret
;-------------------------- Display Track --------------------------
NoteList: ;Store the displaying characters in PM.db "C2 ","C2#","D2 ","D2#","E2 ","F2 ","F2#","G2 ","G2#","A2 ","A2#","B2 ","C3 ","C3#","D3 ","D3#","E3 ","F3 ","F3#","G3 ","G3#","A3 ","A3#","B3 ","C4 ","C4#","D4 ","D4#","E4 ","F4 ","F4#","G4 ","G4#","A4 ","A4#","B4 ","C5 ","C5#","D5 ","D5#","E5 ","F5 ","F5#","G5 ","G5#","A5 ","A5#","B5 ","C6 ","C6#","D6 ","D6#","E6 ","F6 ","F6#","G6 ","G6#","A6 ","A6#","B6 ","C7 ","C7#","D7 ","D7#","E7 ","F7 ","F7#","G7 ","G7#","A7 ","A7#","B7 "
Displaytrack: ;Displays the Track that is stored in the "editing"
Page: 6
C:\Users\M\Desktop\codeextracted\Dialogues.asm
spaceLDI YH,high(TrackLengthAddress) ;set up Y pointer for the Track length LDI YL,low(TrackLengthAddress)
ld varB,Y ;load Track length from SRAM
LDI YH,high(FirstNoteAdress) ;Set up Y pointer to the First Note in SRAMLDI YL,low(FirstNoteAdress)
clr tempregcall clrdis ;clear display
clr status ;clears LCD note position information (used for displaying notes in the right spots)
DisplaytrackLoop: ;Loops Every time a new note is being displayed;--------------------- show pitchldi ZL,low(2*NoteList) ;Sets Z pointer to the PM address with the string of Note Valuesldi ZH,high(2*NoteList)
call csrpitch ;Sets the cursor to the pitch position of the current note. i.e. the bottom left. current note is determined from status
ld parA,Y+ ;loads the Note(Pitch) Value from SRAM and increment Ydec parAldi tempreg,3 ;parA *3 (Beacuse the string for pitch is 3 bytes long)mul parA,tempregmov parA,r0add ZL,parA ;add the pitch*3 to the Z pointer. Now Z pointer points to the string that corresponds with the Pitchclr tempregadc ZH,tempreg
LPM tempreg , Z+ ;load first char of pitch string and increment Zsts $C000,tempreg ;write itcall busylcdLPM tempreg , Z+ ;load second char...sts $C000,tempregcall busylcdLPM tempreg , Z+sts $C000,tempregcall busylcd
call csrtopleft ;moves cursor to the top left of the note square on the LCD. (uses status reg to determine note position);--------------------- show volumeld parA,Y+ ;load Volume from SRAM and increment Ydec parAcall showlcd ;display Volume;--------------------- show Note Lengthld parA,Y+ ;load NoteLength from SRAM and increment Y (now Y points to pitch of the next note)ldi tempreg,4 ;add 4 to the NotelLength because the custom character use that part of the CgRAM address of the LCD add parA,tempregcall showlcd ;display NoteLength
inc status ;Increment Note Number
call findnotepos ;puts NoteNUmber into suboutcp subout,varBbrne Displaytrackloop ;case NoteNumber = Tracklength -> Exit, else loopret;-------------------------- Note Track --------------------------
NoteTrackDialogue: ;Allows for input of a new Track with up to 80 notes
call defineVolumeAndNoteLengthChars;Sets the custom characters of the LCD to the volume and NoteLength characters
call clrdis ;clear display
Page: 7
C:\Users\M\Desktop\codeextracted\Dialogues.asm
call NoteTrackPattern ;Display the Note Track grid, into which the notes are inserted
call csrreset ;Reset the cursor to pos 0
NoteTrackLoop: ;Loops for every new note that is put inclr varAclr varBclr varC
;---------------------- pitch inputcall csrpitch ;Move cursor to pitch, pointed to by statusmov tempreg,statussbr tempreg,128 ;use NOTE input, by setting flag in status registermov status,tempregcall waitreadbtn ;wait and read button until it is pressed
ldi tempreg,0b11110010cpse subout,tempregcpse tempreg,tempregjmp NoteTrackEnd ;case D/Exit is pressed -> Exit
mov parA,suboutcall showlcd ;show the Note input (e.g. "F")mov varA,subout ;save varA = pitch
;--------------------- octave inputOctaveInput:
call csrbtmright ;moves to the cursor to the bottom right pos in the note square
call LoadDefaultOct ;check if a default octave was setcpi subout,0brne DefaultOctSet ;Case no -> continue, Otherwise jump over the octav
e input loop
mov tempreg,statuscbr tempreg,128mov status,tempreg ;set flag for Number Inputcall waitreadbtn
cpi subout,35 ;# set VarC=1breq SharpDetected ;branches to set varC
DefaultOctSet:mov parA,suboutcall showlcd ;writes Octavemov varB,subout ;save VarB = octave
subi varB,48call POSconverter ;takes VarA,VarB,varC to make a note value
ldi parA,0call StoreToSRAM ;store Note Value to SRAM
;--------------------- Volume Inputcall csrtopleft
call LoadDefaultVol ;Loads default volumecpi subout,0brne DefaultVolumeSet ;case subout = 0 -> coninute. Otherwise skip Volume
input
mov tempreg,statuscbr tempreg,128mov status,tempreg ;set Number Inputcall waitreadbtnsubi subout,48 ;Go from LCD number -> Binary number
DefaultVolumeSet:ldi parA,1call StoreToSRAM ;store Volume to SRAMmov parA,suboutdec parAcall showlcd ;write Volume using custom chars
;--------------------- NoteLengthInputcall csrtopright ;move cursor to the top right of the note square
Page: 8
C:\Users\M\Desktop\codeextracted\Dialogues.asm
call LoadDefaultLen ;loads default note length from SRAMcpi subout,0brne DefaultLengthSet ;case DefaultNoteLength = 0 -> continue, Otherwise
skip Notelengthinput
mov tempreg,statuscbr tempreg,128mov status,tempreg ;set Number Inputcall waitreadbtn ;wait until button is read
DefaultLengthSet:mov parA,suboutsubi parA, 49 ;LCD numbers -> computable numberscall showlcd ;write Note Length
subi subout,53ldi parA,2call StoreToSRAM ;store Note Length to SRAM
inc status ;increment Note Number (moving to next note soon)jmp NoteTrackLoop ;move to next note
;--------------------- BranchesSharpDetected: ;set varC, sharp flag
ldi varC,1jmp OctaveInput
NoteTrackEnd:LDI YH,high(TrackLengthAddress) ;set Y pointer for the track length address ("editi
ng")LDI YL,low(TrackLengthAddress)call findnotepos ;find the note positionst Y,subout ;store the last note position as track length
ret
LoadDefaultOct: ;loads the default octave value from SRAMldi YL,low(DefaultOctaveAddress)ldi YH,high(DefaultOctaveAddress)ld subout,Ycpi subout,0breq LoadDefaultOctEndldi tempreg,48add subout,tempreg
LoadDefaultOctEnd:ret
LoadDefaultVol: ;loads the default Volume value from SRAMldi YL,low(DefaultVolumeAddress)ldi YH,high(DefaultVolumeAddress)ld subout,Y
ret
LoadDefaultLen: ;loads the default NoteLength value from SRAMldi YL,low(DefaultLengthAddress)ldi YH,high(DefaultLengthAddress)ld subout,Ycpi subout,0breq LoadDefaultLenEndldi tempreg,53add subout,tempreg
LoadDefaultLenEnd:ret
StoreToSRAM: ;stores subout to SRAM,takes parA = 0-2 for: (pitch/octave/sharp)nmbr, Volume, Length. Also takes status (note address)
push XLpush XHpush YLpush YH
Page: 9
C:\Users\M\Desktop\codeextracted\Dialogues.asm
push suboutLDI YH,high(FirstNoteAdress);set up Y pointer for the First note of editing spaceLDI YL,low(FirstNoteAdress)call findnotepos ;stores the Note position in suboutldi tempreg,3mul subout,tempregmov tempreg,r0 ;NotePos*3 = SRAM location of the Note that is saved toclcadd YL, tempreg ;add Notepos*3 to the Addressclr tempregadc YH,tempregclcadd YL,parA ;add 0 for note, 1 for volume and 2 for Lendth to the Addre
ssclr tempregadc YH,tempreg
pop subout
st Y, subout ;store information in SRAM
pop YHpop YLpop XHpop XL
ret
POSconverter: ;converts Pitch(varA), octave(varB), sharp(varC) into a number(C2=1,C2#=2,...). Starting with octave 2clr subout
cpi varA,65breq POSconverterA ;case pitch = A -> add 10cpi varA,66breq POSconverterB ;case pitch = B -> add 12cpi varA,67breq POSconverterC ;case pitch = C -> add 1cpi varA,68breq POSconverterD ;case pitch = D -> add 3cpi varA,69breq POSconverterE ;case pitch = E -> add 5cpi varA,70breq POSconverterF ;case pitch = F -> add 6cpi varA,71breq POSconverterG ;case pitch = G -> add 8
ReturnPOSconverterVarA:ldi tempreg,12subi varB,2 ;remove octave offset by 2mul tempreg,varB ;*new* octave*12 mov tempreg,r0add subout,tempreg ;add the octave on top of the pitch valueadd subout,VarC ;add 1 in case of #jmp POSconverterEnd ;Exit
POSconverterA:ldi tempreg,10add subout,tempregjmp ReturnPOSconverterVarAPOSconverterB:ldi tempreg,12add subout,tempregjmp ReturnPOSconverterVarAPOSconverterC:inc suboutjmp ReturnPOSconverterVarAPOSconverterD:ldi tempreg,3add subout,tempregjmp ReturnPOSconverterVarAPOSconverterE:ldi tempreg,5
Page: 10
C:\Users\M\Desktop\codeextracted\Dialogues.asm
add subout,tempregjmp ReturnPOSconverterVarAPOSconverterF:ldi tempreg,6add subout,tempregjmp ReturnPOSconverterVarAPOSconverterG:ldi tempreg,8add subout,tempregjmp ReturnPOSconverterVarAPOSconverterEnd:ret
NoteTrackPattern: ;Displays the NoteTrack input matrixpush parAldi parA,0b11011011 ;loads []square character from LCD character tableldi tempreg,0 ;reset counter
NoteTrackPatternLoop:inc tempreg ;increment countercall showlcd ;write the squarecpi tempreg,40brne NoteTrackPatternLoop ;case counter = 40 -> Exitpop parA
ret
notetrackpatternClear: ;same thing as NoteTrackPattern just with an empty character. It deletes the Patterncall csrresetldi parA,0b00100000clr tempregnotetrackpatternClearLoop:call showlcdinc tempregcpi tempreg,40brne notetrackpatternClearLoopret
;-------------------------- Beat Clock --------------------------BeatClockDialogue: ;determines the Beats Per Minute (BPM)
call clrdiscall Clockprompt ;ask user to input beat clock speed 0-240call BlinkingA ;blinks A and waits until it has been pressedcall CaptureThreeDigits ;captures a 3 digit number and displays the input livecall beatsunits ;display " beats/ min" after the entered valuests BeatSpeedAddress, subout;save beat speed to SRAM
ret
ClockPromptA:.db "Beat frequency ? (range 0-240) beats/min",0 ;define input prompt range (0-240)ClockPrompt:
LDI ZL, LOW(2*ClockPromptA) ;load PM address into Z
LDI ZH, HIGH(2*ClockPromptA)call printlcd ;print onto lcd
ret
beatsunitsA:.db " beats/ min",0 ;put units at end of beat clock dialogbeatsunits:
LDI ZL, LOW(2*beatsunitsA) ;load PM address into Z
LDI ZH, HIGH(2*beatsunitsA)call printlcd ;print onto lcd
ret
;-------------------------- Default Volume --------------------------
DefaultVolumeDialogue:
Page: 11
C:\Users\M\Desktop\codeextracted\Dialogues.asm
call clrdiscall VolumePrompt ;ask user to input default volume 0-100%call keyAcall CaptureThreeDigitscall percentsign ;units at end of dialogue
ret
VolumePromptA:.db "Default Volume % range 0 to 100",0 ;% 0-100
VolumePrompt:LDI ZL, LOW(2*VolumePromptA)LDI ZH, HIGH(2*VolumePromptA)call printlcd
ret
percentsignA:.db "%",0 ;put units at end of default Volume dialoguepercentsign:
LDI ZL, LOW(2*percentsignA) ;load PM address into Z
LDI ZH, HIGH(2*percentsignA)call printlcd ;print onto lcd
ret
;*************************** Other Prompts ************************
OutOfRangePromptA:.db "Value out of range To continue press A",0
OutOfRangePrompt:LDI ZL,LOW(2*OutofrangePromptA)LDI ZH, HIGH(2*OutofrangePromptA)call clrdiscall printlcd
ret
UnexpectedErrorA:.db "Unexpected Error",0
UnexpectedError:LDI ZL, LOW(2*UnexpectedErrorA)LDI ZH, HIGH(2*UnexpectedErrorA)call clrdiscall printlcd
ret
Page: 12
C:\Users\M\Desktop\codeextracted\DelayAndMisc.asm
;*************************** Delay ****************************hugedel: ;makes a very big delay, mainly for debugging
call bigdelcall bigdelcall bigdelcall bigdelcall bigdelcall bigdelcall bigdelcall bigdel
retMedDel: ;medium delay for sounds
rcall Del49msrcall Del49msrcall Del49ms
retBigDEL: ;big delay, made for LCD
rcall Del49msrcall Del49msrcall Del49msrcall Del49msrcall Del49ms
ret;DEL49ms: ;All these delays are based on: 1. Loading a big number into X 2. counting it down
LDI XH, HIGH(65535)LDI XL, LOW (65535)rcall count
retDEL15ms:
LDI XH, HIGH(19997)LDI XL, LOW (19997)rcall count
ret;DEL4P1ms:
LDI XH, HIGH(5464)LDI XL, LOW (5464)rcall count
ret;DEL500mus:
call del100muscall del100muscall del100muscall del100muscall del100mus
ret
DEL100mus:LDI XH, HIGH(131)LDI XL, LOW (131)rcall count
retcount: ;counts down X, for all the delay functions
SBIW XL, 1BRNE count
ret
;*************************** Debugging ****************************showLED: ;displays parA on the LEDs
out PortB,parAret
showled1: ;displays 00000011push parAldi parA,0b11111100call showledpop parA
ret
Page: 1
C:\Users\M\Desktop\codeextracted\DelayAndMisc.asm
showled2:push parAldi parA,0b11110011call showledpop parA
ret
showled3:push parAldi parA,0b11001111call showledpop parA
ret
showled4:push tempregldi tempreg,0b00111111call showledpop tempreg
ret
showlcd1: ;shows A on the csr position on LCDldi parA, 65call showlcd
retshowlcd2:
ldi parA,66call showlcd
ret
lcdfill: ;fills lcd with the first 80 characters in the CgRAM tablepush varAcall clrdis ;clear displaycall busyLCD ;wait for display readyldi varA,0lcdfillloop:mov parA,varAcall showlcd ;displays parA character from CgRAM tableinc varA ;counts up to 80cpi varA,80brne lcdfillloop ;case varA = 80 -> Exitpop varA
ret
SRAMtest:LDI YH,high(FirstNoteAdress)LDI YL,low(FirstNoteAdress)
clr tempregcall clrdis
SRAMtestLoop:ld parA,Y+call showledcall showlcdcall keyAinc tempregcpi tempreg,10brne SRAMtestloopret
LCDfillNumbers:clr tempregclr varA
clr tempregFirstLoop:ldi parA,48
SecondLoop:inc tempregcall showlcd
Page: 2
C:\Users\M\Desktop\codeextracted\DelayAndMisc.asm
inc parAcpi parA,58breq FirstLoopldi varA,80cpse tempreg,varAjmp SecondLoopret;*************************** MISC ****************************Custom1: ;These are the symbols for the welcome Patter.db 0b11111, 0b11111, 0b11111, 0b11111, 0,0,0,0Custom2:.db 0,0,0,0, 0b11111,0b11111, 0b11111, 0b11111Custom3:.db 0b11111,0b01111,0b00111,0b00011,0b00001,0,0,0Custom4:.db 0b00000,0b00000,0b00000,0b10000,0b11000,0b11100,0b11110,0b11111Custom5:.db 0b11111,0b11110,0b11100,0b11000,0b10000,0b00000,0b00000,0b00000Custom6:.db 0b11000,0b11100,0b11110,0b11111,0b11111,0b11111,0b11111,0b11110Custom7:.db 0b00011,0b00111,0b01111,0b11111,0b11111,0b11111,0b11111,0b01111Custom8:.db 0b00000,0b10001,0b11011,0b11111,0b11111,0b11111,0b11111,0b11111
LoadWelcomeChars: ;Loads the Welcome characters into the 8 "custom" spaces of the LCD CgRAMpush ZLpush ZH
ldi tempreg,$40 ;0b01000000 enables CgRAM address writests $8000, tempreg ;Sets up the CgRAM Address to 0call busyLCD ;wait for LCD ready
LDI ZL, LOW(2*Custom1) ;Loads PM address into ZLDI ZH, HIGH(2*Custom1)call CharWriteLCDsgram ;Writes the character inforamtion at Z into CgRAM 0+. Increments Z. CgRAM address is internally incremented in LCD
LDI ZL, LOW(2*Custom2) ;Z setup for char2LDI ZH, HIGH(2*Custom2)call CharWriteLCDsgram ;same as above...
LDI ZL, LOW(2*Custom3)LDI ZH, HIGH(2*Custom3)call CharWriteLCDsgram
LDI ZL, LOW(2*Custom4)LDI ZH, HIGH(2*Custom4)call CharWriteLCDsgram
LDI ZL, LOW(2*Custom5)LDI ZH, HIGH(2*Custom5)call CharWriteLCDsgram
LDI ZL, LOW(2*Custom6)LDI ZH, HIGH(2*Custom6)call CharWriteLCDsgram
LDI ZL, LOW(2*Custom7)LDI ZH, HIGH(2*Custom7)call CharWriteLCDsgram
LDI ZL, LOW(2*Custom8)LDI ZH, HIGH(2*Custom8)call CharWriteLCDsgram
pop ZHpop ZLret
Page: 3
C:\Users\M\Desktop\codeextracted\DelayAndMisc.asm
WelcomePattern: ;Makes the SYNTH pattern for The Initial Screencall LoadWelcomeChars ;Loads the characters required for the pattern into the LCDs CgRAMcall clrdis ;clear displaycall MakeS ;makes the S charactercall MakeYcall MakeNcall makeTcall makeH
ret
MakeN: ;Displays the N by filling characters in different linesldi parA, 8call csrset ;set csr to pos 8ldi parA,$FFcall showlcd ;fill the characterldi parA,0b00100000call showlcd ;emptyldi parA,0b00100000call showlcd ;emptyldi parA,$FFcall showlcd ;fill
;----------------row 2
ldi parA,48call csrset ;set csr to pos 48 (2nd row, 8th column)ldi parA,$FFcall showlcd ;fillldi parA,$FFcall showlcd ;fillldi parA,0b00100000call showlcd ;emptyldi parA,$FFcall showlcd ;fill
;----------------row 3
ldi parA,28 ;pos 28 (3rd row, 8th col)call csrsetldi parA,$FFcall showlcd ;same as aboveldi parA,0b00100000call showlcdldi parA,$FFcall showlcdldi parA,$FFcall showlcd
;----------------row 4
ldi parA,68call csrsetldi parA,$FFcall showlcdldi parA,0b00100000call showlcdldi parA,0b00100000call showlcdldi parA,$FFcall showlcdret
MakeY:;----------------row 1ldi parA,4call csrsetldi parA,$FFcall showlcdldi parA,0b00100000call showlcdldi parA,$FF
Page: 4
C:\Users\M\Desktop\codeextracted\DelayAndMisc.asm
call showlcd
;----------------row 2
ldi parA,44call csrsetldi parA,2call showlcdldi parA,7call showlcdldi parA,4call showlcd;----------------row 3
ldi parA,25call csrsetldi parA,$FFcall showlcd
;----------------row 4ldi parA,65call csrsetldi parA,$FFcall showlcdret
MakeS:;----------------row 1call csrreset ;pos 0ldi parA,$FFcall showlcdcall showlcdldi parA,5call showlcd ;use custom character 6 to make A rounded shape
;----------------row 2
ldi parA,40call csrsetldi parA,$FFcall showlcdldi parA,3call showlcd
;----------------row 3
ldi parA,21call csrsetldi parA,2call showlcdldi parA,$FFcall showlcd
;----------------row 4ldi parA,60call csrsetldi parA,6call showlcdldi parA,$FFcall showlcdcall showlcdretMakeH:ldi parA,17call csrset
ldi parA,$FFcall showlcdldi parA,0b00100000call showlcdldi parA,$FFcall showlcd
Page: 5
C:\Users\M\Desktop\codeextracted\DelayAndMisc.asm
ldi parA,57call csrsetldi parA,$FFcall showlcdldi parA,1call showlcdldi parA,$FFcall showlcd
ldi parA,37call csrsetldi parA,$FFcall showlcdldi parA,0call showlcdldi parA,$FFcall showlcd
ldi parA,77call csrsetldi parA,$FFcall showlcdldi parA,0b00100000call showlcdldi parA,$FFcall showlcdret
MakeT:ldi parA,13call csrset
ldi parA,$FFcall showlcdcall showlcdcall showlcd
ldi parA,54call csrsetldi parA,$FFcall showlcd
ldi parA,34call csrsetldi parA,$FFcall showlcd
ldi parA,74call csrsetldi parA,$FFcall showlcdret
ResetTrackDefaults: ;Sets the default Octave,Volume and Notelength. Customisable via UI later on.
ldi YL,low(DefaultOctaveAddress)ldi YH,high(DefaultOctaveAddress)ldi tempreg,4st Y,tempreg ;store Octave to SRAM
ldi YL,low(DefaultVolumeAddress)ldi YH,high(DefaultVolumeAddress)ldi tempreg,5st Y,tempreg ;store Volume to SRAM
ldi YL,low(DefaultLengthAddress)ldi YH,high(DefaultLengthAddress)ldi tempreg,3st Y,tempreg ;store Notelength to SRAM
ret
Page: 6
C:\Users\M\Desktop\codeextracted\DelayAndMisc.asm
findnotepos: ;returns the current Note position (NMBR) used in NoteTrack and PlayNoteTrack of "dialogues.asm"
mov subout,status ;load from status registercbr subout,128 ;delete KeyPad (nmbr or note) flag
ret
ConvertToDecimalDigits: ;takes parA and returns decimal digits as:varA = 100s,varB = 10s and VarC = 1s digit
clr tempreg ;counts up to the input parameterclr varA ;100s (output)clr varB ;10s (output)clr varC ;1s (output)
ConvertToDecimalDigitsLoop:cp tempreg, parAbreq ConvertToDecimalDigitsEnd ;case parA = tempreg (i.e. counter = input)
-> Exit nad return varA,varB,varCinc tempreg ;increment counterinc varC ;increment 1s digitcpi varC,10brne ConvertToDecimalDigitsLoop ;case 1s digit = 10 (i.e. 1s digit overflow
) -> continue. Otherwise Loopldi varC,0 ;reset 1s digitinc varB ;increment 10s digitcpi varB,10brne ConvertToDecimalDigitsLoop ;case 10s digit = 10 (i.e. overflow) -> Con
tinue. Otherwise Loopldi varB,0 ;reset 10s digitinc varA ;incremetn 100s digitrjmp ConvertToDecimalDigitsLoop ;loop. 100s digit cannot overflow as parA r
ange 0-255ConvertToDecimalDigitsEnd:ret
;---------------------------- Save/Load --------------------------------SaveTrack: ;moves data in SRAM from "editing" address to "save" address
call StorageSelect ;sets up Y for storage (parA = 0,1,2 for A,B,C) and Z for "editing" space
clr tempregSaveTrackLoop:
ld varA,Z+ ;loads register according to Z pointer. Z is pointed at "editing" SRAM space Z increments
st Y+, varA ;stores the register in the Y address that was set up by SaveStorageSelect Y increments
inc tempreg ;increment countercpi tempreg,240brne SaveTrackLoop ;case 240 SRAM addresses have been saved to -> Exit. Otherw
ise Loopret
LoadTrack: ;Moves Data in SRAM from save address into "editing" address
call StorageSelect ;Sets up Y pointer for the save address and Z for "editing" space
clr tempregLoadTrackLoop:
ld varA,Y+ ;loads register from save spacest Z+, varA ;saves that register into editing space inc tempregcpi tempreg,240brne LoadTrackLoop ;case counter = 240 -> Exit. Otherwise Loop
ret
StorageSelect: ;Takes parA(0-2) loads Y with the Track Length Adress and Z with the "editing" Track length address
cpi parA,0breq UseStorageA ;case parA = 0 -> set up storage Acpi parA,1breq UseStorageB ;case parA = 1 -> set up storage Bcpi parA,2
Page: 7
C:\Users\M\Desktop\codeextracted\DelayAndMisc.asm
breq UseStorageC ;case parA = 2 -> set up storage Ccall UnexpectedError ;case Anything else. Unexpected error occur
ed. function sits in "DelayAndMisc.asm"
UseStorageA:ldi YH,high(ASaveTrackLengthAddress) ;load SaveA address into Yldi YL,low(ASaveTrackLengthAddress)rjmp FinishStorageSelect ;Exit
UseStorageB:ldi YH,high(BSaveTrackLengthAddress)ldi YL,low(BSaveTrackLengthAddress)rjmp FinishStorageSelect
UseStorageC:ldi YH,high(CSaveTrackLengthAddress)ldi YL,low(CSaveTrackLengthAddress)rjmp FinishStorageSelect
FinishStorageSelect:ldi ZH,high(TrackLengthAddress) ;Load "editing" address into Zldi ZL,low(TrackLengthAddress)clr tempreg
ret
EraseSram: ;an attempt to erase SRAM during initialisation
ldi XL,low(280)ldi XH,high(280)
EraseSramLoop:LDI YH,high(ASaveTrackLengthAddress)LDI YL,low(ASaveTrackLengthAddress)ldi tempreg,$FFst Y+,tempregclr tempreginc XLadc XH,tempregcpi XH,8breq EraseSramEndjmp EraseSramLoop
EraseSramEnd:ret
;*************************** ADC ****************************ADCInit:
ldi TempReg, $83 ; ADC Interrupt Disabled, ADC Enabledout ADCSR, TempReg ; ADC Free Run Mode, Prescaler:CK/8
;adcchannel = varA.def ADCDL = r23.def ADCDH = r24.def FlagReg = r25
ret
ADCsel:out ADMUX, varA ; Channel Selection
retDCATrig: SBI ADCSR, 6 ; Cause a Conversion
IN ADCDL, ADCL ; Read in Low ByteIN ADCDH, ADCH ; Read in High Byte
ADCCLR: SBI ADCSR, 4 ; Reset ADIFIN TempReg,ADCSR ; Read in StatusSBIC ADCSR, 4 ; Wait till the Interrupt flagRJMP ADCCLR ; is cleared
RET
Page: 8
C:\Users\M\Desktop\codeextracted\Tracks.asm
HelloSound: ;Plays the Hello Sound in the beginningldi tempreg,24 ;stores Note values to NoteReg1 to initiate a Note and clears N
otereg1 to stop it. mov NoteReg1,tempreg;uses MedDEl for timing (delay)ldi tempreg,12mov NoteReg2,tempregldi tempreg,33mov NoteReg3,tempregcall MedDel
ldi tempreg,28mov NoteReg1,tempregldi tempreg,16mov NoteReg2,tempregldi tempreg,33mov NoteReg3,tempregcall MedDel
ldi tempreg,31mov NoteReg1,tempregldi tempreg,24mov NoteReg2,tempregldi tempreg,31mov NoteReg3,tempregcall MedDel
ldi tempreg,36mov NoteReg1,tempregldi tempreg,24mov NoteReg2,tempregldi tempreg,24mov NoteReg3,tempregcall MedDelcall MedDel
clr tempregmov NoteReg1,tempreg
ret
JingleBIP: ;an attempt of making a base beat to the jingle bells trackcliseildi tempreg,66add tempreg,varAmov NoteReg2,tempreg
call DEL15mscall DEL15ms
ldi tempreg,61add tempreg,varAmov NoteReg2,tempreg
call DEL15mscall DEL15ms
clr NOteReg2cliret
JingleBells:sei ;set interrupts onldi tempreg,0b00001111and DynReg1,tempregand DynReg2,tempreg
ldi tempreg,0b10010000add DynReg1,tempregadd DynReg2,tempreg
;(varA)
Page: 1
C:\Users\M\Desktop\codeextracted\Tracks.asm
ldi varA, 2 ; set up the varA value 3* oct for addition to the note valueldi tempreg,12mul varA,tempregmov varA,r0
call JingleBellspartA ;uses the same methods as "Hello" to play sounds. But it relies on delays that are calculated from BPM as can be seen belowcall JingleBellspartBcall JingleBellspartAcall JingleBellspartCcliret
NoteEnd:cliclr NoteReg1
call DEL15mscall DEL15mscall DEL15mscall DEL15mscall DEL15msseiret
QuarterDel:call EightDelret
EightDel:call EightDelscall EightDelscall EightDels
ret
EightDels: ;BPM depedendent delay between notes. call BPMtoSECcall BPMdel
ret
JingleBellspartC:ldi tempreg,13add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall NoteEnd
ldi tempreg,13add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall NoteEnd
ldi tempreg,11add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall NoteEnd
ldi tempreg,8add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall NoteEnd
ldi tempreg,6add tempreg,varAmov NoteReg1,tempreg
Page: 2
C:\Users\M\Desktop\codeextracted\Tracks.asm
call QuarterDelcall QuarterDelcall QuarterDelcall NoteEndret
JingleBellsPartB:; --------------------------------------------- ...one horse open sleighclr NoteReg1ldi tempreg,10add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall NoteEnd
ldi tempreg,8add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall NoteEnd
ldi tempreg,8add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall NoteEnd
ldi tempreg,10add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall NoteEnd
ldi tempreg,8add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall QuarterDelcall NoteEndret
JingleBellspartA:;----------------------------------------
ldi tempreg,13add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall QuarterDelcall NoteEnd
ldi tempreg,10add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall NoteEnd
ldi tempreg,10add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall NoteEnd
Page: 3
C:\Users\M\Desktop\codeextracted\Tracks.asm
ldi tempreg,10add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall QuarterDelcall NoteEnd
ldi tempreg,10add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall NoteEnd
ldi tempreg,10add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall NoteEnd
ldi tempreg,10add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall QuarterDelcall NoteEnd;--------------------------...Jingle all the way...ldi tempreg,10add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall NoteEnd
ldi tempreg,13add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall NoteEnd
ldi tempreg,6add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall EightDelclr NoteReg1
ldi tempreg,8add tempreg,varAmov NoteReg1,tempreg
call EightDelscall NoteEnd
ldi tempreg,10add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall QuarterDelcall QuarterDelcall NoteEndclicall QuarterDelsei;------------------------------ ...way,
;------------------------ Oh what a fun it is to ride in a...
Page: 4
C:\Users\M\Desktop\codeextracted\Tracks.asm
ldi tempreg,11add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall NoteEnd
ldi tempreg,11add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall NoteEnd
ldi tempreg,11add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall EightDelcall NoteEnd
ldi tempreg,11add tempreg,varAmov NoteReg1,tempreg
call EightDelscall NoteEnd
ldi tempreg,11add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall NoteEnd
ldi tempreg,10add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall NoteEnd
ldi tempreg,10add tempreg,varAmov NoteReg1,tempreg
call QuarterDelcall NoteEnd
ldi tempreg,10add tempreg,varAmov NoteReg1,tempreg
call EightDelscall NoteEnd
ldi tempreg,10add tempreg,varAmov NoteReg1,tempreg
call EightDelscall NoteEnd;------------------------------------------- ... in aret
SRAMJingleBells: ;an attempt to save jinglebells to SRAM. However we stopped, because time didn't allow....
Page: 5
C:\Users\M\Desktop\codeextracted\Tracks.asm
ldi tempreg,0b00001111and DynReg1,tempregand DynReg2,tempreg
ldi tempreg,0b10010000add DynReg1,tempregadd DynReg2,tempreg
;(varA)ldi varA, 2 ; set up the varA value 3* oct for addition to the note valueldi tempreg,12mul varA,tempregmov varA,r0
LDI YH,high(ASaveTrackLengthAddress)LDI YL,low(ASaveTrackLengthAddress)ldi tempreg,31st Y+,tempreg
call JingleBellspartASRAMcall JingleBellspartBSRAMcall JingleBellspartASRAMcall JingleBellspartCSRAMret
StoreJingleNoteToSRAM:push tempregst Y+,tempregldi tempreg,5st Y+,tempregpop tempreg
ret
StoreJingleQuarterDel:push tempregldi tempreg,3st Y+,tempregpop tempreg
ret
StoreJingleEigthDel:push tempregldi tempreg,2st Y+,tempregpop tempreg
retStoreJingleEigthDels:
push tempregldi tempreg,1st Y+,tempregpop tempreg
ret
JingleBellspartCSRAM:ldi tempreg,13call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
ldi tempreg,13call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
Page: 6
C:\Users\M\Desktop\codeextracted\Tracks.asm
ldi tempreg,11call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
ldi tempreg,8call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
ldi tempreg,6call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
ldi tempreg,6call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
ldi tempreg,6call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
ret
JingleBellsPartBSRAM:; --------------------------------------------- ...one horse open sleighclr NoteReg1ldi tempreg,10call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
ldi tempreg,8call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
ldi tempreg,8call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
ldi tempreg,10call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
ldi tempreg,8call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDelldi tempreg,8
Page: 7
C:\Users\M\Desktop\codeextracted\Tracks.asm
call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel ret
JingleBellspartASRAM:;---------------------------------------- ldi tempreg,13call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDelldi tempreg,13call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
ldi tempreg,10call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
ldi tempreg,10call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
ldi tempreg,10call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDelldi tempreg,10call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
ldi tempreg,10call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
ldi tempreg,10call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
ldi tempreg,10call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
ldi tempreg,10call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
Page: 8
C:\Users\M\Desktop\codeextracted\Tracks.asm
;--------------------------...Jingle all the way...ldi tempreg,10call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
ldi tempreg,13call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
ldi tempreg,6call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDelcall StoreJingleEigthDelclr NoteReg1
ldi tempreg,8call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleEigthDels
ldi tempreg,10call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDelldi tempreg,10call StoreJingleNoteToSRAMmov NoteReg1,tempregcall StoreJingleQuarterDelldi tempreg,10call StoreJingleNoteToSRAMmov NoteReg1,tempregcall StoreJingleQuarterDel clicall StoreJingleQuarterDelsei;------------------------------ ...way,
;------------------------ Oh what a fun it is to ride in a...
ldi tempreg,11call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
ldi tempreg,11call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
ldi tempreg,11call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDelcall StoreJingleEigthDel
Page: 9
C:\Users\M\Desktop\codeextracted\Tracks.asm
ldi tempreg,11call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleEigthDels
ldi tempreg,11call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
ldi tempreg,10call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
ldi tempreg,10call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleQuarterDel
ldi tempreg,10call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleEigthDels
ldi tempreg,10call StoreJingleNoteToSRAMmov NoteReg1,tempreg
call StoreJingleEigthDels ;------------------------------------------- ... in aret
Page: 10
C:\Users\M\Desktop\codeextracted\SoundL.asm
;***********************************************************************************************************; Sound Generator Functions;***********************************************************************************************************
;-----------------;Tables;-----------------
; Square Note Delays, starting at C2; Format = ct:rm
SqrNoteVals:.dw $EF1F,$E178,$D52F,$C91D,$BE66,$B30A,$A915,$9F71,$967D,$8E0C,$8613,$7F73,$7773,$7142,$6A6B,$6472,$5F31,$597C,$5476,$5048,$4B3F,$4706,$430A,$3F47,$3C47,$385F,$3535,$3239,$2F67,$2D42,$2A3B,$2824,$2660,$247D,$227B,$205D,$1E23,$1C30,$1B65,$191D,$184C,$165F,$151E,$1412,$1330,$123E,$113D,$102E,$0F11,$0E18,$0D4D,$0D72,$0C26,$0B30,$0B71,$0A09,$0968,$091F,$0861,$0817,$0777,$070C,$0759,$0647,$0613,$0668,$0548,$0504,$054C,$0471,$0431,$040B,$0444,$047A,$0354,$0324,$0309,$0334,$035C,$027E,$025A,$0238,$0219,$0206
; DDS M values, starting at C2
DDSMTable:.dw $0225 , $0245 , $0268 , $028C , $02B3 , $02DC , $0308 , $0336 , $0367 , $039B , $03D2 , $0
; Wavetable goes here
;---------- Note and Dynamic Registers -----------
; |7 |6 |5 |4 |3 |2 |1 |0 |; DynRegX = |AMP3|AMP2|AMP1|AMP0|PWM1|PWM0|CHC0|DIR0|
; AMP values --> amplitude values to give how loud the square wave should be; PWM values --> SQR: dictates how wide the pulse width is for the wave. DDS: dictates which wavetable to use (and therefore which wave form to play) [DDS not operational in this version]; CHC value --> When 0, Sqr wave is output. When 1, DDS generation is implemented; DIR value --> For Sqr Only. When 1, output is currently ON. When 0, output is currently off.
; |7 |6 |5 |4 |3 |2 |1 |0 |; NoteRegX = |NTE7|NTE6|NTE5|NTE4|NTE3|NTE2|NTE1|NTE0|
;-------------------------------------------------
OSC1_TRIG:in R4,SREG ; save Sregpush TempApush TempB ; Look after values used in main codepush ZLpush ZHsbrc DynReg1,1 ; Check DynReg1 for which waveform should be generatedrcall SQR1 ; Square Generator module called heresbrs DynReg1,1rcall SQR1pop ZHpop ZLpop TempB ; Restore values used in main codepop TempAout SREG,r4 ; get SREG backreti ; Timer 0 Compare interrupt return
; OSC2_TRIG and OSC3_TRIG are identical in function to OSC1_TRIG, with minor variations
OSC2_TRIG:in R4,SREGpush TempApush TempBpush ZLpush ZHsbrc DynReg2,1
Page: 1
C:\Users\M\Desktop\codeextracted\SoundL.asm
noprcall SQR2pop ZHpop ZLpop TempBpop TempAout SREG,r4reti ; Timer 1 Compare A interrupt return
OSC3_TRIG:in R4,SREGpush TempApush TempBpush TempCpush TempDpush ZLpush ZH
rcall SQR3
pop ZHpop ZLpop TempDpop TempCpop TempBpop TempAout SREG,r4reti ; Timer 2 Compare interrupt Return
;-------------------------------; SQUARE WAVE GENERATORS;-------------------------------
;---------------- Definition of ctX and rmX -----------------
; ctX = Count Register - a register which stores the multiple of 256 which must be counted through as a delay
; rmX = Remainder Register - register which stores the remainder of the count once ctX hits zero, in which case OCRX is given the value held in this register
;-------------------- GENERAL FUNCTIONS ---------------------
SqrExit:ret
;---------------------- SQUARE OSC #1 -----------------------
SQR1:cpi ct1,$00 ; Checks if ct1 has hit zero yetbreq oneH ; Branches to oneH if it has subi ct1,$01 ; Decrements ct1 if <> 0rjmp SqrExit
oneH: cpi rm1,$00 ; Checks if rm1 has been set to zero yet. If it has, then OCR has been set to remainder already, and the entire counter has now reached zero.
breq oneOut ; Outputs new amplitude if counter has reached zeroout OCR0,rm1 ; Sets OCR0 to the remainder counterldi rm1, 0 ; Sets rm1 as a flag register now, so the program knows
that on the next OSC1_TRIG call, the counter has reached zerorjmp SqrExit
oneOut: rcall DAC1PartOne ; Activates DAC1 so that it is ready to receive amplitude data from this oscillator while keeping the other DACs disabled.
rcall SQR1_OUT ; Generates Output and sends it out of portrcall DAC1PartTwo ; Latches the DAC onto the new amplitude data until it
changes againrcall SQR1_TIM ; Resets timer, using note and PWM information
ldi tempA, $01 ;sbrs DynReg1,0 ; Checks the DIR0 bit, and performs a NOT operation on
it using
Page: 2
C:\Users\M\Desktop\codeextracted\SoundL.asm
rjmp Swap1A ; Swap1A or Swap1Brjmp Swap1B ;
Swap1A: add DynReg1,tempAret
Swap1B: sub DynReg1,tempAret
SQR1_OUT:mov TempA,DynReg1 ; copy Dynamics Register to holder registerandi TempA, 0b11110000 ; get pure amplitude out of copied dynamics registersbrc DynReg1,0 ; Depending on whether wave form is currently up or dow
n, does twos complement or notneg TempA ; Two's complement of the positive amplitude gives the
corresponding negative amplitude apparentlyout PORTB,TempA ; outputs new amplitude to portret
SQR1_TIM:mov TempB,NoteReg1 ; Load Holder register with the note value requ
iredldi ZH, high(SqrNoteVals*2) ; Load the position of the delay table into Zldi ZL, low(SqrNoteVals*2) ;add ZL, tempB ; Each location at Z holds half a word, therefo
re we need to double our pointer valueldi tempA,$00adc ZH,tempAadd ZL, tempBldi tempA,$00adc ZH,tempAlpm rm1, Z+ ; Loads new Remainder Register value, increment
s Z to get Count Register value for next line of codelpm ct1, Zsbiw Z,$01 ; Returns Z pointer to start of word.; PWM checkersbrc DynReg1, 2 ; If PWM0 = 1 , halve pulse width cyclerjmp HalfWidth1 ; Function setting half period depending on PWM
and whether amplitude is ON or OFFsbrc DynReg1, 3 ; If PWM1 = 1 , halve width cyclerjmp HalfWidth1ldi tempA, $FFout OCR0,tempA ;Sets OCR0 back to FF so that the Count Registe
r counts in multiples of 256ret
HalfWidth1:lsr rm1 ; Halves high delay valuelsr ct1ldi tempA,0brbc 0,NoCar1 ; If no carry, skip additionldi tempA, 0b10000000
NoCar1: add rm1,tempA ; Adds carry if presentsbrc DynReg1, 0 ; Checks if up or down. IF up, add 50% delaylpm tempA,Z+add rm1, tempAsbrc DynReg1, 0lpm tempA, Zadc ct1, tempAsbiw Z,$01ret
;---------------------- SQUARE OSC #2 -----------------------; Exact Same Principles as SQUARE OSC #1
SQR2:cpi ct2,$00 breq twoHsubi ct2,$01 rjmp SqrExit
twoH: cpi rm2,$00 breq twoOut ldi tempA, 0out OCR1AH,tempA
Page: 3
C:\Users\M\Desktop\codeextracted\SoundL.asm
out OCR1AL,rm2ldi rm2, 0
rjmp SqrExit
twoOut: rcall DAC2PartOnercall SQR2_OUTrcall DAC2PartTworcall SQR2_TIM
ldi tempA, $01sbrs DynReg2,0rjmp Swap2Arjmp Swap2B
Swap2A: add DynReg2,tempAret
Swap2B: sub DynReg2,tempAret
SQR2_OUT:mov TempA,DynReg2andi TempA, 0b11110000sbrc DynReg2,0neg TempAout PORTB,TempAret
SQR2_TIM:mov TempB,NoteReg2ldi ZH, high(SqrNoteVals*2)ldi ZL, low(SqrNoteVals*2)add ZL, tempBldi tempA,$00adc ZH,tempAadd ZL, tempBldi tempA,$00adc ZH,tempAlpm rm2, Z+lpm ct2, Zsbiw Z,$01
sbrc DynReg2, 2rjmp HalfWidth2sbrc DynReg2, 3rjmp HalfWidth2ldi tempA, $FFldi tempB, 0out OCR1AH, tempBout OCR1AL, tempAret
HalfWidth2:lsr rm2lsr ct2ldi tempA,0brbc 0,NoCar2ldi tempA, 0b10000000
NoCar2: add rm2,tempAsbrc DynReg2, 0lpm tempA,Z+add rm2, tempAsbrc DynReg2, 0lpm tempA, Zadc ct2, tempAsbiw Z,$01ret
;---------------------- SQUARE OSC #3 -----------------------; Exact Same Principles as SQUARE OSC #1; Minor difference is that the ct3:rm3 registers are NOT immediate registers.
Page: 4
C:\Users\M\Desktop\codeextracted\SoundL.asm
SQR3:ldi tempC,$00cp ct3,tempC breq thrHldi tempD, $01sub ct3,tempD rjmp SqrExit
thrH: cp rm3,tempC breq thrOut out OCR2,rm3mov rm3, tempCrjmp SqrExit
thrOut: rcall DAC3PartOnercall SQR3_OUTrcall DAC3PartTworcall SQR3_TIM
ldi tempA, $01sbrs DynReg3,0rjmp Swap3Arjmp Swap3Bret
Swap3A: add DynReg3,tempAret
Swap3B: sub DynReg3,tempAret
SQR3_OUT:mov TempA,DynReg3andi TempA, 0b11110000sbrc DynReg3,0neg TempAout PORTB,TempAret
SQR3_TIM:mov TempB,NoteReg3ldi ZH, high(SqrNoteVals*2)ldi ZL, low(SqrNoteVals*2)add ZL, tempBldi tempA,$00adc ZH,tempAadd ZL, tempBldi tempA,$00adc ZH,tempAlpm rm3, Z+lpm ct3, Zsbiw Z,$01
sbrc DynReg3, 2rjmp HalfWidth3sbrc DynReg3, 3rjmp HalfWidth3ldi tempA, $FFout OCR2,tempAret
HalfWidth3:lsr rm3lsr ct3ldi tempA,0brbc 0,NoCar3ldi tempA, 0b10000000
NoCar3: add rm3,tempAsbrc DynReg3, 0lpm tempA,Z+add rm3, tempAsbrc DynReg3, 0lpm tempA, Zadc ct3, tempA
Page: 5
C:\Users\M\Desktop\codeextracted\SoundL.asm
sbiw Z,$01ret
; DAC functionsDAC1PartOne:
nopldi tempA, 0b11111110 ; Set CS* in DAC1 to 0out PORTD, tempAnop ; Delayldi tempA, 0b11111100 ; Set WR* in DAC1 to 0out PORTD, tempAnopret
DAC1PartTwo:nopldi tempA, 0b11111110 ; Set WR* in DAC1 to 1out PORTD, tempAnop ; Delaynopldi tempA, 0b11111111 ; Set CS* in DAC1 to 1out PORTD, tempAnop
ret
DAC2PartOne:nopldi tempA, 0b11111011 ; Set CS* in DAC2 to 0out PORTD, tempAnop ; Delayldi tempA, 0b11110011 ; Set WR* in DAC2 to 0out PORTD, tempAnopret
DAC2PartTwo:nopldi tempA, 0b11111011 ; Set WR* in DAC2 to 1out PORTD, tempAnop ; Delaynopldi tempA, 0b11111111 ; Set CS* in DAC2 to 1out PORTD, tempAnop
ret
DAC3PartOne:nopldi tempA, 0b11101111 ; Set CS* in DAC3 to 0out PORTD, tempAnop ; Delayldi tempA, 0b11001111 ; Set WR* in DAC3 to 0out PORTD, tempAnopret
DAC3PartTwo:nopldi tempA, 0b11101111 ; Set WR* in DAC3 to 1out PORTD, tempAnop ; Delaynopldi tempA, 0b11111111 ; Set CS* in DAC3 to 1out PORTD, tempAnop
ret
Page: 6
C:\Users\M\Desktop\codeextracted\Sequencer.asm
.def NoteLength = r23 ;prev varC
.def NoteNumber = r21 ;prev varA
MainSequenceFunction: ;plays notes from saveA,saveB,saveC at the same time. (looping)
seiclr NoteNumber
MainSequenceLoop: ;Loops over each quarter beatcall QuarterNote ;Handles the note inside a quater beatcall BPMtoSEC ;loads BPM form SRAM and converts it into millisecondssbiw Y,5 ;subtract the number of milliseconds that this loop & f
unctions take (i.e. quarternote)call BPMdel ;Delays for a given number of millisecondsrjmp MainSequenceLoop
MainSequenceFunctionEnd:ret
;*************************** General ********************************QuarterNote:
ldi tempreg,0b11000000 ;and tempreg,NoteLength ; Checking if NoteLength has overflowed i.e 00XXXXXXcpi tempreg,0 ; If it has, get a new NOTEbreq GetNote ;
GetNoteReturn:call CheckStopNote ; Checks if Loaded Notes should still be playing at t
his q-beatldi tempreg, 0b01000000 ; -add NoteLength, tempreg ; Increment NoteLength counterclr tempreg ; -adc NoteNumber, tempreg ; Moves to next position if NoteLength counter overfl
owsret
GetNote: ; Loads note from memoryclr NoteLength ; Started again. thus rest NoteLength
call CheckTrackEnd ;checks if max track has been fully played-> Resets NoteNumber if
clr parAcall TrackLoopercall LoadNote ;takes parA,0,1,2 for the storage space and NoteNumber
for Note
ldi parA,1call TrackLoopercall LoadNote
ldi parA,2call TrackLoopercall LoadNote
rjmp GetNoteReturn
TrackLooper: ; takes parA,0,1,2 for storage location and resets NoteNumber(NoteNmbr) if Track length was reached
push NoteNumberLDI YH,high(FirstNoteAdress)LDI YL,low(FirstNoteAdress)call SequenceStorageSelectsbiw YL:YH,1ld tempreg,Y
SSSLoop: ;Make Divide, give rest functionsub NoteNumber,tempreg
brmi SSSbranchjmp SSSLoop
SSSbranch:add NoteNumber,tempreg
Page: 1
C:\Users\M\Desktop\codeextracted\Sequencer.asm
cp tempreg,NoteNumberbrne TrackLooperBranchclr NoteNumber
TrackLooperBranch:pop NoteNumber
ret
CheckTrackEnd: ;checks all three tracks and loops them until the longest track has finished. It then loops everything.
push NoteNumberpush varBpush varC
call LoadTrackLengths ; load to NoteNumber,varB,varC the track lengthscall FindBiggestVar
pop varCpop varBpop NoteNumber
cp NoteNumber,suboutbrne CheckTrackFinalclr NoteNumber
CheckTrackFinal:ret
LoadTrackLengths: ;loads track lengths into NoteNumber,varB,varCldi parA,0call SequenceStorageSelectsbiw YL:YH,1ld NoteNumber,Yldi parA,1call SequenceStorageSelectsbiw YL:YH,1ld varB,Yldi parA,2call SequenceStorageSelectsbiw YL:YH,1ld varC,Y
ret
FindBiggestVar: ;outputs biggest of NoteNumber,varB,varCclr subout
FindBiggestVarLoop:
clndec NoteNumberBRPL FBVLAclr NoteNumberFBVLA:clndec varBBRPL FBVLBclr varBFBVLB:clndec varCBRPL FBVLCclr varCFBVLC:
inc subout
clr tempregcpse NoteNumber,tempreg
Page: 2
C:\Users\M\Desktop\codeextracted\Sequencer.asm
jmp FindBiggestVarLoopcpse varB,tempregjmp FindBiggestVarLoopcpse varC,tempregjmp FindBiggestVarLoop
ret
BPMtoSEC: ;takes BPM in parA and returns milliseconds in Yldi YL,Low(BeatSpeedAddress)ldi YH,High(BeatSpeedAddress)ld parA,Yldi XL,low(60000)ldi XH,high(60000)clr YLclr YH
BPMtoSECloop:sub XL,parAclr tempregsbc XH,tempregBRCS BPMtoSECendADIW Y,1jmp BPMtoSECloop
BPMtoSECend:ret
BPMDel:BPMDelL:
cpi varB,0brne BPMDelLoopldi varB,7clnSBIW Y,1brmi BPMDelEnd
BPMDelLoop:dec varBcall readbtncpi subout,0b11100001breq ExitSequencerjmp BPMDelL
ExitSequencer:clicall waitbtnupjmp Beta
BPMDelEnd:ret
CheckStopNote: ;Checks if note has ended yet, and if it has then it gives amplitude 0.
push varB
ldi varB,0b00000011 ; Extracts SaveA Current Note Lengthand varB,NoteLengthlsl varBlsl varBlsl varBlsl varBlsl varBlsl varB
ldi tempreg,0b11000000 ;and tempreg,NoteLength ;
cp varB,tempreg ; Compare SaveA NL with Counter, and stop if equalbreq StopSA ;
ContA:
ldi tempreg,0b11000000 ;and tempreg,NoteLength ;
Page: 3
C:\Users\M\Desktop\codeextracted\Sequencer.asm
ldi varB,0b00001100 ; Extracts SaveB Current Note Lengthand varB,NoteLength ;lsl varBlsl varBlsl varBlsl varB
cp varB,tempreg ; Compare SaveB NL with Counter, and stop if equalbreq StopSB ;
ContB:
ldi tempreg,0b11000000 ;and tempreg,NoteLength
ldi varB,0b00110000 ; Extracts SaveC Current Note Lengthand varB,NoteLength ;lsl varBlsl varB
cp varB,tempreg ; Compare SaveC NL with Counter, and stop if equalbreq StopSC ;jmp CheckStopNoteEnd
; StopSX makes Relevant DynReg amplitudes = 0
StopSA:ldi tempreg,0b00001111and DynReg1,tempregjmp ContA
StopSB:ldi tempreg,0b00001111and DynReg2,tempregjmp ContB
StopSC:ldi tempreg,0b00001111and DynReg3,tempreg
CheckStopNoteEnd:pop varBret
;********************************* Load Note ************************************************
LoadNote: ;loads notes from SRAM and saves it to DynReg1 and NoteReag. parA takes 0-2, NoteNumber is parameter for note NMBR
call SequenceStorageSelect
clr r0clcldi tempreg,3mul NoteNumber,tempregadd YL,r0clr tempregadc YH,tempreg
cpi parA,0breq LoadFromSAcpi parA,1breq LoadFromSBcpi parA,2breq LoadFromSC
LoadFromSA:push YLpush YHLDI YH,high(ASaveTrackLengthAddress)LDI YL,low(ASaveTrackLengthAddress)ld tempreg,Ypop YHpop YL
Page: 4
C:\Users\M\Desktop\codeextracted\Sequencer.asm
cpi tempreg,1breq SANoteregZero
ld tempreg,Y+mov NoteReg1,tempreg
ld parA,Y+mov subout, DynReg1call DynRegConvertermov DynReg1,subout
ld parA,Yldi tempreg,0b11111100and NoteLength,tempregadd NoteLength,parAjmp LoadNoteEnd
SANoteregZero:clr NoteReg1ldi tempreg,0b00001111and Dynreg1,tempregjmp LoadNoteEnd
LoadFromSB:push YLpush YHLDI YH,high(BSaveTrackLengthAddress)LDI YL,low(BSaveTrackLengthAddress)ld tempreg,Ypop YHpop YLcpi tempreg,1breq SBNoteregZero
ld tempreg,Y+mov NoteReg2,tempreg
ld parA,Y+mov subout, DynReg2call DynRegConvertermov DynReg2,suboutld parA,Y
ldi tempreg,0b11110011and NoteLength,tempreglsl parAlsl parAadd NoteLength,parAjmp LoadNoteEnd
SBNoteregZero:clr NoteReg2ldi tempreg,0b00001111and Dynreg2,tempregjmp LoadNoteEnd
LoadFromSC:push YLpush YHLDI YH,high(CSaveTrackLengthAddress)LDI YL,low(CSaveTrackLengthAddress)ld tempreg,Ypop YHpop YLcpi tempreg,1breq SCNoteregZero
ld tempreg,Y+mov NoteReg3,tempreg
Page: 5
C:\Users\M\Desktop\codeextracted\Sequencer.asm
ld parA,Y+mov subout, DynReg3call DynRegConvertermov DynReg3,suboutld parA,Y
ldi tempreg,0b11001111and NoteLength,tempreglsl parAlsl parAlsl parAlsl parAadd NoteLength,parAjmp LoadNoteEnd
SCNoteregZero:clr NoteReg3ldi tempreg,0b00001111and Dynreg3,tempregjmp LoadNoteEnd
LoadNoteEnd:ret
DynRegConverter: ;outputs an amplitude according to parA input (0-5)cpi parA,0breq DynRegConverterAcpi parA,1breq DynRegConverterBcpi parA,2breq DynRegConverterCcpi parA,3breq DynRegConverterDcpi parA,4breq DynRegConverterEcpi parA,5breq DynRegConverterF
DynRegConverterA:ldi varB,0b10000000call SetUpDynregjmp DynRegConverterEndDynRegConverterB:ldi varB,0b10010000call SetUpDynregjmp DynRegConverterEndDynRegConverterC:ldi varB,0b10100000call SetUpDynregjmp DynRegConverterEndDynRegConverterD:ldi varB,0b10110000call SetUpDynregjmp DynRegConverterEndDynRegConverterE:ldi varB,0b11010000call SetUpDynregjmp DynRegConverterEndDynRegConverterF:ldi varB,0b11110000call SetUpDynregjmp DynRegConverterEnd
DynRegConverterEnd:ret
SetUpDynreg:ldi tempreg,0b00001111and subout, tempreg ;clears the 4 most significant bitsadd subout, varB
ret
Page: 6
C:\Users\M\Desktop\codeextracted\Sequencer.asm
SequenceStorageSelect: ;takes 0-3 for parA and sets up Y for the first note
LDI YH,high(FirstNoteAdress)LDI YL,low(FirstNoteAdress)
push NoteNumberpush parAinc parA
SequenceStorageSelectLoop:cpi parA,0breq SequenceStorageSelectEnd
ldi tempreg,$96add YL,tempregclr tempregadc YH,tempreg
ldi tempreg,$96add YL,tempregclr tempregadc YH,tempreg
dec parAjmp SequenceStorageSelectLoop
SequenceStorageSelectEnd:pop parApop NoteNumber
ret
Page: 7