66

Laboratory Report Sample

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