;###############################################################################
;                                                                              #
; avrmusicbox V0.38 zweistimmige Klangerzeugung (Spieluhr) mit ATMEGA8/88      #
; (c)2006 Jörg Wolfram   joerg@jcwolfram.de   		                       #
;                                                                              #
; Dieses Programm ist freie Software. Sie können es unter den Bedingungen      #
; der GNU General Public License, wie von der Free Software Foundation         #
; veröffentlicht, weitergeben und/oder modifizieren, entweder gemäss           #
; Version 2 der Lizenz oder (nach Ihrer Option) jeder späteren Version.        #
;                                                                              #
; Die Veröffentlichung dieses Programms erfolgt in der Hoffnung, daß es        #
; Ihnen von Nutzen sein wird, aber OHNE IRGENDEINE GARANTIE, auch ohne die     #
; implizite Garantie der MARKTREIFE oder der VERWENDBARKEIT FÜR EINEN          #
; BESTIMMTEN ZWECK. Details finden Sie in der GNU General Public License.      #
;                                                                              #
; Sie sollten ein Exemplar der GNU General Public License zusammen mit         #
; diesem Programm erhalten haben. Falls nicht, schreiben Sie an die Free       #
; Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110,    #
; USA.                                                                         #
;                                                                              #
; Jede Nutzung der Software/Informationen nonkonform zur GPL oder ausserhalb   #
; des Geltungsbereiches der GPL ist untersagt!                                 #
;                                                                              #
;###############################################################################

;set controller type (08 or 88)
.define		ctype 	88

;###############################################################################
; system ram
;###############################################################################
;-------------------------------------------------------------------------------
; data for channel 1
;-------------------------------------------------------------------------------
;sysram+0		position wave LSB
;sysram+1		position wave MSB
;sysram+2		increment wave LSB
;sysram+3		increment wave MSB
;sysram+4		wavetable LSB
;sysram+5		wavetable MSB 
;sysram+6		position envelope LSB
;sysram+7		position Envelope MSB
;sysram+8		increment envelope LSB
;sysram+9	 	increment envelope MSB
;sysram+10		envelope table LSB
;sysram+11		envelope table MSB 
;sysram+12	 	volume
;sysram+13		pitch shift (halftones)

;-------------------------------------------------------------------------------
; data for channel 2
;-------------------------------------------------------------------------------
;sysram+16		position wave LSB
;sysram+17		position wave MSB
;sysram+18		increment wave LSB
;sysram+19		increment wave MSB
;sysram+20		wavetable LSB
;sysram+21		wavetable MSB 
;sysram+22		position envelope LSB
;sysram+23		position Envelope MSB
;sysram+24		increment envelope LSB
;sysram+25	 	increment envelope MSB
;sysram+26		envelope table LSB
;sysram+27		envelope table MSB 
;sysram+28	 	volume
;sysram+29		pitch shift (halftones)

;the sum of the volumes for both channels must not exceed 255!
;-------------------------------------------------------------------------------
; data for music sequencer
;-------------------------------------------------------------------------------
;sysram+32		store address for begin of notes
;sysram+33		store address for begin of notes
;sysram+34		actual speed
;sysram+35		selected song
;sysram+36		00/ff -> play/"preview"
;sysram+37		Merker für verses
;sysram+38		store song Volume 1
;sysram+39		store song Volume 2
;sysram+40		button was pressed until playing

;-------------------------------------------------------------------------------
;header:
;16 bytes text (can be used for LC-Display)
;1 byte count of verses, if bit 6 is set, the last two reduces volume
;1 byte speed (click frequency divider)
;2 bytes volume channel 1 and 2
;music data (will be repeated for each verse):
; 0CNNNNNN			note for channel C
; 1111dddd			Delta-Clicks, 11110000 means end
; 1000Ceee			envelope speed für channel C
; 1001C000 vvvvvvvv		volume für channel C	
; 1010C000 nnnnnnnn		pitch shift for channel C
; 1011C000 llllllll hhhhhhhh	address wavetable for channel C
; 1100Cxxx llllllll hhhhhhhh	address envelopetable for channel C
; 11100000			end of "preview"
; 11101111			filling byte
;-------------------------------------------------------------------------------

    .include "definitions/interrupts.inc"
    .include "definitions/registers.inc"
    
;r0 and r1 are used for multiplications 
.def		speed1	=r2			;selected speed
.def		byte0	=r3			;0x00 as constant
.def		byte127	=r4			;0x7f as constant
.def		byte128	=r5			;0x80 as constant
.def		byte254	=r6			;0xfe as constant
.def		epl	=r7			;envelope-pointer low
.def		eph	=r8			;envelope-pointer high			
.def		wal	=r9			;wave offset for DDS low	
.def		wah	=r10			;wave offset for DDS high
.def		eal	=r11			;envelope offset low
.def		eah	=r12			;envelope offset high	
.def		verse	=r13			;verse counter
.def		sreg	=r14			;save SREG
.def		sigl	=r15			;LSB of audio signal

.def		temp1	=r16			;temporary register for isr
.def		temp2	=r17			;temporary register for isr
.def		sigh	=r18			;MSB of audio signal
.def		temp 	=r19			;temporary register
.def		anfno	=r20			;note request
.def		anfev	=r21			;envelope request
.def		deltac	=r22			;delta-click counter
.def		status	=r23			;channel- und clickstatus
.def		wpl	=r24			;wavepointer low	
.def		wph	=r25			;wavepointer high

.if	ctype == 08
.equ		ddstab	= 0x100			;dds offsets
.equ		eofftab	= 0xf0			;envelope offsets
.equ		sysram	= 0x80			;system variables
.equ		stack	= 0x7f			;stack
.endif
.if	ctype == 88
.equ		ddstab	= 0x100			;dds offsets
.equ		eofftab	= 0x200			;envelope offsets
.equ		sysram	= 0x240			;system variables
.equ		stack	= 0x3ff			;stack
.endif

.cseg
;###############################################################################
; jump to initialization
;###############################################################################
.org 0x00
		rjmp	init
		
;###############################################################################
; the external interrupt 1 disables himself, its only needed for wakeup from
; power down mode
;###############################################################################
.org	INT1addr
.if ctype == 88
		out	EIMSK,byte0
.endif
.if ctype == 08
		out	GICR,byte0
.endif
		reti

.org	OVF1addr
.include	"routines/timerint.inc"

;###############################################################################
; initialize
;###############################################################################
init:		cli				;disable interrupts
		ldi	temp,HIGH(stack)	;stack
		out	SPH,temp
		ldi	temp,LOW(stack)
		out	SPL,temp

		ldi	temp,0x00	
		mov	byte0,temp		;0-byte used as constant
		ldi	temp,0x7f
		mov	byte127,temp		;0x7f-byte used as constant
		ldi	temp,0x80
		mov	byte128,temp		;0x80-byte used as constant
		ldi	temp,0xfe
		mov	byte254,temp		;0xfe-byte used as constant

		ldi	ZH,HIGH(wtab1*2)	;start wavetable
		ldi	ZL,LOW(wtab1*2)		
		sts	sysram+4,ZL
		sts	sysram+5,ZH
		sts	sysram+20,ZL
		sts	sysram+21,ZH

		ldi	ZH,HIGH(etab1*2)	;start envelope-table
		ldi	ZL,LOW(etab1*2)	
		sts	sysram+10,ZL
		sts	sysram+11,ZH
		sts	sysram+26,ZL
		sts	sysram+27,ZH

		mov	status,byte0		;clear all requests

.if 	ctype == 88
		in	temp,MCUCR
		andi	temp,0xef		;enable pullups
		out	MCUCR,temp
calibration:	ldi	temp,0x40
		sts	OSCCAL,temp

.endif
.if 	ctype == 08
		in	temp,SFIOR
		ori	temp,0x04		;enable pullups
		out	SFIOR,temp
calibration:	ldi	temp,0xa8
		out	OSCCAL,temp
.endif

		
;-------------------------------------------------------------------------------
; port configuration
;-------------------------------------------------------------------------------
		ldi	temp,0xff		;outputs 
		out	DDRB,temp		;port B direction
		ldi	temp,0x00
		out	PORTB,temp		;set 

		ldi	temp,0xff		;outputs
		out	DDRC,temp		;port C direction
		ldi	temp,0x00
		out	PORTC,temp		;set

		ldi	temp,0xf7		;outputs except PD3
		out	DDRD,temp		;port D direction
		ldi	temp,0x08
		out	PORTD,temp		;set

;-------------------------------------------------------------------------------
; interrupt and timer configuration for mega88
;-------------------------------------------------------------------------------
.if 	ctype == 88
		ldi	temp,0x00		;interrupts level-tr
		sts	EICRA,temp

		ldi	temp,0x05		;sleep-mode pwrdown
		out	SMCR,temp		

		out	EIMSK,byte0		;disable external interrupts

		ldi	temp,0x01
		sts	TIMSK1,temp		;enable timer 1 overflow
		
		ldi	temp,0xa2		;FAST-PWM-Mode 8 Bit (channel A + B)
		sts	TCCR1A,temp
		ldi	temp,0x19		;FAST-PWM-Mode
		sts	TCCR1B,temp

		ldi	temp,0x00
		sts	ICR1H,temp
		ldi	temp,0xff
		sts	ICR1L,temp

		mov	sigh,byte127
		mov	sigl,byte0
		sts	OCR1AH,byte0		;MSB-value
		sts	OCR1AL,sigh		;LSB-value
		sts	OCR1BH,byte0		;MSB-value
		sts	OCR1BL,sigh		;LSB-value
		
		ldi	temp,0xa3		;Konfiguration Timer 0
		out	TCCR0A,temp	
		ldi	temp,0x01		;Konfiguration Timer 0
		out	TCCR0B,temp	

		out	OCR0B,byte127
		out	OCR0A,byte127

		sts	sysram+35,byte0		;Startvalue song
		sts	sysram+40,byte0	
.endif		
;-------------------------------------------------------------------------------
; interrupt and timer configuration for mega8
;-------------------------------------------------------------------------------
.if	ctype == 08
		ldi	temp,0xa0		;sleepmode pwrdown / interrupts level-tr
		out	MCUCR,temp
		out	GICR,byte0		;disable external interrupts
		ldi	temp,0x04
		out	TIMSK,temp		;enable timer 1 overflow
		ldi	temp,0xf2		;FAST-PWM-Mode 8 Bit (channel A + B)
		out	TCCR1A,temp
		ldi	temp,0x19		;FAST-PWM-Mode for timer 2
		out	TCCR1B,temp

		ldi	temp,0x00
		out	ICR1H,temp
		ldi	temp,0xff
		out	ICR1L,temp

		mov	sigh,byte127
		mov	sigl,byte0
		out	OCR1AH,byte0		;MSB-value
		out	OCR1AL,sigh		;LSB-value
		out	OCR1BH,byte0		;MSB-value
		out	OCR1BL,sigh		;LSB-value
		ldi	temp,0x79		;Konfiguration Timer 2
		out	TCCR2,temp	
		out	OCR2,byte127
		sts	sysram+35,byte0		;Startvalue song
		sts	sysram+40,byte0	
.endif		

;-------------------------------------------------------------------------------
; copy tables to RAM
;-------------------------------------------------------------------------------
		cli
koptab:		ldi	ZH,HIGH(ztab*2)		;address of dds-offsets in ROM
		ldi	ZL,LOW(ztab*2) 
		ldi	YH,HIGH(ddstab)		;address of table in RAM
		ldi	YL,LOW(ddstab)	
		ldi	temp1,128		;counter
koptab1:	lpm	temp,Z+			;read from ROM	
		st	Y+,temp			;write to RAM
		dec	temp1			;next value
		brne	koptab1			;loop
		
		ldi	ZH,HIGH(eadd*2)		;address of envelope-offsets in ROM
		ldi	ZL,LOW(eadd*2)
		ldi	YH,HIGH(eofftab)	;address of table in RAM
		ldi	YL,LOW(eofftab)
		ldi	temp1,16		;counter
koptab2:	lpm	temp,Z+			;read from ROM	
		st	Y+,temp			;write to RAM
		dec	temp1			;next value
		brne	koptab2			;loop
		
;-------------------------------------------------------------------------------
; the player
;-------------------------------------------------------------------------------
.include	"routines/player.inc"
.include	"routines/sequencer.inc"
		
;###############################################################################
;the area of tables
;###############################################################################
		
		.include "tables/musictables.inc"

eadd:		.db	0x00,0x04,0x00,0x02,0x55,0x01,0x00,0x01
		.db	0xab,0x00,0x80,0x00,0x55,0x00,0x40,0x00

;-------------------------------------------------------------------------------
;music-data
;- Der Mond ist aufgegangen
;- Schlaf, Kindlein schlaf
;- Guten Abend, Gute Nacht
;- Die Blümelein sie schlafen
;- Weisst du wieviel Sternlein stehen
;- Wer hat die schönsten Schaefchen
;-------------------------------------------------------------------------------
.include	"music/definitions.inc"

md1:
.include	"music/der_mond_ist_aufgegangen"		;Song 1
md2:
.include	"music/schlaf_kindlein_schlaf"			;Song 2
md3:
.include	"music/guten_abend_gut_nacht"			;Song 3
md4:
.include	"music/die_bluemelein_sie_schlafen"		;Song 4
md5:
.include	"music/weisst_du_wieviel_sternlein_stehen"	;Song 5
md6:
.include	"music/emptysong"				;Song 6
