;CodeVisionAVR C Compiler V1.24.4 Standard ;(C) Copyright 1998-2004 Pavel Haiduc, HP InfoTech s.r.l. ;http://www.hpinfotech.com ;e-mail:office@hpinfotech.com ;Chip type : ATmega32 ;Program type : Application ;Clock frequency : 8.000000 MHz ;Memory model : Small ;Optimize for : Size ;(s)printf features : int, width ;(s)scanf features : int, width ;External SRAM size : 0 ;Data Stack size : 512 byte(s) ;Heap size : 0 byte(s) ;Promote char to int : No ;char is unsigned : Yes ;8 bit enums : Yes ;Enhanced core instructions : On ;Automatic register allocation : On .EQU UDRE=0x5 .EQU RXC=0x7 .EQU USR=0xB .EQU UDR=0xC .EQU SPSR=0xE .EQU SPDR=0xF .EQU EERE=0x0 .EQU EEWE=0x1 .EQU EEMWE=0x2 .EQU EECR=0x1C .EQU EEDR=0x1D .EQU EEARL=0x1E .EQU EEARH=0x1F .EQU WDTCR=0x21 .EQU MCUCR=0x35 .EQU GICR=0x3B .EQU SPL=0x3D .EQU SPH=0x3E .EQU SREG=0x3F .DEF R0X0=R0 .DEF R0X1=R1 .DEF R0X2=R2 .DEF R0X3=R3 .DEF R0X4=R4 .DEF R0X5=R5 .DEF R0X6=R6 .DEF R0X7=R7 .DEF R0X8=R8 .DEF R0X9=R9 .DEF R0XA=R10 .DEF R0XB=R11 .DEF R0XC=R12 .DEF R0XD=R13 .DEF R0XE=R14 .DEF R0XF=R15 .DEF R0X10=R16 .DEF R0X11=R17 .DEF R0X12=R18 .DEF R0X13=R19 .DEF R0X14=R20 .DEF R0X15=R21 .DEF R0X16=R22 .DEF R0X17=R23 .DEF R0X18=R24 .DEF R0X19=R25 .DEF R0X1A=R26 .DEF R0X1B=R27 .DEF R0X1C=R28 .DEF R0X1D=R29 .DEF R0X1E=R30 .DEF R0X1F=R31 .EQU __se_bit=0x80 .EQU __sm_mask=0x70 .EQU __sm_adc_noise_red=0x10 .EQU __sm_powerdown=0x20 .EQU __sm_powersave=0x30 .EQU __sm_standby=0x60 .EQU __sm_ext_standby=0x70 .MACRO __CPD1N CPI R30,LOW(@0) LDI R26,HIGH(@0) CPC R31,R26 LDI R26,BYTE3(@0) CPC R22,R26 LDI R26,BYTE4(@0) CPC R23,R26 .ENDM .MACRO __CPD2N CPI R26,LOW(@0) LDI R30,HIGH(@0) CPC R27,R30 LDI R30,BYTE3(@0) CPC R24,R30 LDI R30,BYTE4(@0) CPC R25,R30 .ENDM .MACRO __CPWRR CP R@0,R@2 CPC R@1,R@3 .ENDM .MACRO __CPWRN CPI R@0,LOW(@2) LDI R30,HIGH(@2) CPC R@1,R30 .ENDM .MACRO __ADDD1N SUBI R30,LOW(-@0) SBCI R31,HIGH(-@0) SBCI R22,BYTE3(-@0) SBCI R23,BYTE4(-@0) .ENDM .MACRO __ADDD2N SUBI R26,LOW(-@0) SBCI R27,HIGH(-@0) SBCI R24,BYTE3(-@0) SBCI R25,BYTE4(-@0) .ENDM .MACRO __SUBD1N SUBI R30,LOW(@0) SBCI R31,HIGH(@0) SBCI R22,BYTE3(@0) SBCI R23,BYTE4(@0) .ENDM .MACRO __SUBD2N SUBI R26,LOW(@0) SBCI R27,HIGH(@0) SBCI R24,BYTE3(@0) SBCI R25,BYTE4(@0) .ENDM .MACRO __ANDD1N ANDI R30,LOW(@0) ANDI R31,HIGH(@0) ANDI R22,BYTE3(@0) ANDI R23,BYTE4(@0) .ENDM .MACRO __ORD1N ORI R30,LOW(@0) ORI R31,HIGH(@0) ORI R22,BYTE3(@0) ORI R23,BYTE4(@0) .ENDM .MACRO __DELAY_USB LDI R24,LOW(@0) __DELAY_USB_LOOP: DEC R24 BRNE __DELAY_USB_LOOP .ENDM .MACRO __DELAY_USW LDI R24,LOW(@0) LDI R25,HIGH(@0) __DELAY_USW_LOOP: SBIW R24,1 BRNE __DELAY_USW_LOOP .ENDM .MACRO __CLRD1S LDI R30,0 STD Y+@0,R30 STD Y+@0+1,R30 STD Y+@0+2,R30 STD Y+@0+3,R30 .ENDM .MACRO __GETD1S LDD R30,Y+@0 LDD R31,Y+@0+1 LDD R22,Y+@0+2 LDD R23,Y+@0+3 .ENDM .MACRO __PUTD1S STD Y+@0,R30 STD Y+@0+1,R31 STD Y+@0+2,R22 STD Y+@0+3,R23 .ENDM .MACRO __POINTB1MN LDI R30,LOW(@0+@1) .ENDM .MACRO __POINTW1MN LDI R30,LOW(@0+@1) LDI R31,HIGH(@0+@1) .ENDM .MACRO __POINTW1FN LDI R30,LOW(2*@0+@1) LDI R31,HIGH(2*@0+@1) .ENDM .MACRO __POINTB2MN LDI R26,LOW(@0+@1) .ENDM .MACRO __POINTW2MN LDI R26,LOW(@0+@1) LDI R27,HIGH(@0+@1) .ENDM .MACRO __POINTBRM LDI R@0,LOW(@1) .ENDM .MACRO __POINTWRM LDI R@0,LOW(@2) LDI R@1,HIGH(@2) .ENDM .MACRO __POINTBRMN LDI R@0,LOW(@1+@2) .ENDM .MACRO __POINTWRMN LDI R@0,LOW(@2+@3) LDI R@1,HIGH(@2+@3) .ENDM .MACRO __GETD1N LDI R30,LOW(@0) LDI R31,HIGH(@0) LDI R22,BYTE3(@0) LDI R23,BYTE4(@0) .ENDM .MACRO __GETD2N LDI R26,LOW(@0) LDI R27,HIGH(@0) LDI R24,BYTE3(@0) LDI R25,BYTE4(@0) .ENDM .MACRO __GETD2S LDD R26,Y+@0 LDD R27,Y+@0+1 LDD R24,Y+@0+2 LDD R25,Y+@0+3 .ENDM .MACRO __GETB1MN LDS R30,@0+@1 .ENDM .MACRO __GETW1MN LDS R30,@0+@1 LDS R31,@0+@1+1 .ENDM .MACRO __GETD1MN LDS R30,@0+@1 LDS R31,@0+@1+1 LDS R22,@0+@1+2 LDS R23,@0+@1+3 .ENDM .MACRO __GETBRMN LDS R@2,@0+@1 .ENDM .MACRO __GETWRMN LDS R@2,@0+@1 LDS R@3,@0+@1+1 .ENDM .MACRO __GETWRZ LDD R@0,Z+@2 LDD R@1,Z+@2+1 .ENDM .MACRO __GETB2MN LDS R26,@0+@1 .ENDM .MACRO __GETW2MN LDS R26,@0+@1 LDS R27,@0+@1+1 .ENDM .MACRO __GETD2MN LDS R26,@0+@1 LDS R27,@0+@1+1 LDS R24,@0+@1+2 LDS R25,@0+@1+3 .ENDM .MACRO __PUTB1MN STS @0+@1,R30 .ENDM .MACRO __PUTW1MN STS @0+@1,R30 STS @0+@1+1,R31 .ENDM .MACRO __PUTD1MN STS @0+@1,R30 STS @0+@1+1,R31 STS @0+@1+2,R22 STS @0+@1+3,R23 .ENDM .MACRO __PUTDZ2 STD Z+@0,R26 STD Z+@0+1,R27 STD Z+@0+2,R24 STD Z+@0+3,R25 .ENDM .MACRO __PUTBMRN STS @0+@1,R@2 .ENDM .MACRO __PUTWMRN STS @0+@1,R@2 STS @0+@1+1,R@3 .ENDM .MACRO __PUTBZR STD Z+@1,R@0 .ENDM .MACRO __PUTWZR STD Z+@2,R@0 STD Z+@2+1,R@1 .ENDM .MACRO __GETW1R MOV R30,R@0 MOV R31,R@1 .ENDM .MACRO __GETW2R MOV R26,R@0 MOV R27,R@1 .ENDM .MACRO __GETWRN LDI R@0,LOW(@2) LDI R@1,HIGH(@2) .ENDM .MACRO __PUTW1R MOV R@0,R30 MOV R@1,R31 .ENDM .MACRO __PUTW2R MOV R@0,R26 MOV R@1,R27 .ENDM .MACRO __ADDWRN SUBI R@0,LOW(-@2) SBCI R@1,HIGH(-@2) .ENDM .MACRO __ADDWRR ADD R@0,R@2 ADC R@1,R@3 .ENDM .MACRO __SUBWRN SUBI R@0,LOW(@2) SBCI R@1,HIGH(@2) .ENDM .MACRO __SUBWRR SUB R@0,R@2 SBC R@1,R@3 .ENDM .MACRO __ANDWRN ANDI R@0,LOW(@2) ANDI R@1,HIGH(@2) .ENDM .MACRO __ANDWRR AND R@0,R@2 AND R@1,R@3 .ENDM .MACRO __ORWRN ORI R@0,LOW(@2) ORI R@1,HIGH(@2) .ENDM .MACRO __ORWRR OR R@0,R@2 OR R@1,R@3 .ENDM .MACRO __EORWRR EOR R@0,R@2 EOR R@1,R@3 .ENDM .MACRO __GETWRS LDD R@0,Y+@2 LDD R@1,Y+@2+1 .ENDM .MACRO __PUTWSR STD Y+@2,R@0 STD Y+@2+1,R@1 .ENDM .MACRO __MOVEWRR MOV R@0,R@2 MOV R@1,R@3 .ENDM .MACRO __INWR IN R@0,@2 IN R@1,@2+1 .ENDM .MACRO __OUTWR OUT @2+1,R@1 OUT @2,R@0 .ENDM .MACRO __CALL1MN LDS R30,@0+@1 LDS R31,@0+@1+1 ICALL .ENDM .MACRO __CALL1FN LDI R30,LOW(2*@0+@1) LDI R31,HIGH(2*@0+@1) CALL __GETW1PF ICALL .ENDM .MACRO __CALL2EN LDI R26,LOW(@0+@1) LDI R27,HIGH(@0+@1) CALL __EEPROMRDW ICALL .ENDM .MACRO __GETW1STACK IN R26,SPL IN R27,SPH ADIW R26,@0+1 LD R30,X+ LD R31,X .ENDM .MACRO __NBST BST R@0,@1 IN R30,SREG LDI R31,0x40 EOR R30,R31 OUT SREG,R30 .ENDM .MACRO __PUTB1SN LDD R26,Y+@0 LDD R27,Y+@0+1 SUBI R26,LOW(-@1) SBCI R27,HIGH(-@1) ST X,R30 .ENDM .MACRO __PUTW1SN LDD R26,Y+@0 LDD R27,Y+@0+1 SUBI R26,LOW(-@1) SBCI R27,HIGH(-@1) ST X+,R30 ST X,R31 .ENDM .MACRO __PUTD1SN LDD R26,Y+@0 LDD R27,Y+@0+1 SUBI R26,LOW(-@1) SBCI R27,HIGH(-@1) CALL __PUTDP1 .ENDM .MACRO __PUTB1SNS LDD R26,Y+@0 LDD R27,Y+@0+1 ADIW R26,@1 ST X,R30 .ENDM .MACRO __PUTW1SNS LDD R26,Y+@0 LDD R27,Y+@0+1 ADIW R26,@1 ST X+,R30 ST X,R31 .ENDM .MACRO __PUTD1SNS LDD R26,Y+@0 LDD R27,Y+@0+1 ADIW R26,@1 CALL __PUTDP1 .ENDM .MACRO __PUTB1PMN LDS R26,@0 LDS R27,@0+1 SUBI R26,LOW(-@1) SBCI R27,HIGH(-@1) ST X,R30 .ENDM .MACRO __PUTW1PMN LDS R26,@0 LDS R27,@0+1 SUBI R26,LOW(-@1) SBCI R27,HIGH(-@1) ST X+,R30 ST X,R31 .ENDM .MACRO __PUTD1PMN LDS R26,@0 LDS R27,@0+1 SUBI R26,LOW(-@1) SBCI R27,HIGH(-@1) CALL __PUTDP1 .ENDM .MACRO __PUTB1PMNS LDS R26,@0 LDS R27,@0+1 ADIW R26,@1 ST X,R30 .ENDM .MACRO __PUTW1PMNS LDS R26,@0 LDS R27,@0+1 ADIW R26,@1 ST X+,R30 ST X,R31 .ENDM .MACRO __PUTD1PMNS LDS R26,@0 LDS R27,@0+1 ADIW R26,@1 CALL __PUTDP1 .ENDM .MACRO __PUTB1RN MOVW R26,R@0 SUBI R26,LOW(-@1) SBCI R27,HIGH(-@1) ST X,R30 .ENDM .MACRO __PUTW1RN MOVW R26,R@0 SUBI R26,LOW(-@1) SBCI R27,HIGH(-@1) ST X+,R30 ST X,R31 .ENDM .MACRO __PUTD1RN MOVW R26,R@0 SUBI R26,LOW(-@1) SBCI R27,HIGH(-@1) CALL __PUTDP1 .ENDM .MACRO __PUTB1RNS MOVW R26,R@0 ADIW R26,@1 ST X,R30 .ENDM .MACRO __PUTW1RNS MOVW R26,R@0 ADIW R26,@1 ST X+,R30 ST X,R31 .ENDM .MACRO __PUTD1RNS MOVW R26,R@0 ADIW R26,@1 CALL __PUTDP1 .ENDM .MACRO __PUTB1RON MOV R26,R@0 MOV R27,R@1 SUBI R26,LOW(-@2) SBCI R27,HIGH(-@2) ST X,R30 .ENDM .MACRO __PUTW1RON MOV R26,R@0 MOV R27,R@1 SUBI R26,LOW(-@2) SBCI R27,HIGH(-@2) ST X+,R30 ST X,R31 .ENDM .MACRO __PUTD1RON MOV R26,R@0 MOV R27,R@1 SUBI R26,LOW(-@2) SBCI R27,HIGH(-@2) CALL __PUTDP1 .ENDM .MACRO __PUTB1RONS MOV R26,R@0 MOV R27,R@1 ADIW R26,@2 ST X,R30 .ENDM .MACRO __PUTW1RONS MOV R26,R@0 MOV R27,R@1 ADIW R26,@2 ST X+,R30 ST X,R31 .ENDM .MACRO __PUTD1RONS MOV R26,R@0 MOV R27,R@1 ADIW R26,@2 CALL __PUTDP1 .ENDM .MACRO __GETB1SX MOVW R30,R28 SUBI R30,LOW(-@0) SBCI R31,HIGH(-@0) LD R30,Z .ENDM .MACRO __GETW1SX MOVW R30,R28 SUBI R30,LOW(-@0) SBCI R31,HIGH(-@0) LD R0,Z+ LD R31,Z MOV R30,R0 .ENDM .MACRO __GETD1SX MOVW R30,R28 SUBI R30,LOW(-@0) SBCI R31,HIGH(-@0) LD R0,Z+ LD R1,Z+ LD R22,Z+ LD R23,Z MOVW R30,R0 .ENDM .MACRO __GETB2SX MOVW R26,R28 SUBI R26,LOW(-@0) SBCI R27,HIGH(-@0) LD R26,X .ENDM .MACRO __GETW2SX MOVW R26,R28 SUBI R26,LOW(-@0) SBCI R27,HIGH(-@0) LD R0,X+ LD R27,X MOV R26,R0 .ENDM .MACRO __GETD2SX MOVW R26,R28 SUBI R26,LOW(-@0) SBCI R27,HIGH(-@0) LD R0,X+ LD R1,X+ LD R24,X+ LD R25,X MOVW R26,R0 .ENDM .MACRO __GETBRSX MOVW R30,R28 SUBI R30,LOW(-@1) SBCI R31,HIGH(-@1) LD R@0,Z .ENDM .MACRO __GETWRSX MOVW R30,R28 SUBI R30,LOW(-@2) SBCI R31,HIGH(-@2) LD R@0,Z+ LD R@1,Z .ENDM .MACRO __LSLW8SX MOVW R30,R28 SUBI R30,LOW(-@0) SBCI R31,HIGH(-@0) LD R31,Z CLR R30 .ENDM .MACRO __PUTB1SX MOVW R26,R28 SUBI R26,LOW(-@0) SBCI R27,HIGH(-@0) ST X,R30 .ENDM .MACRO __PUTW1SX MOVW R26,R28 SUBI R26,LOW(-@0) SBCI R27,HIGH(-@0) ST X+,R30 ST X,R31 .ENDM .MACRO __PUTD1SX MOVW R26,R28 SUBI R26,LOW(-@0) SBCI R27,HIGH(-@0) ST X+,R30 ST X+,R31 ST X+,R22 ST X,R23 .ENDM .MACRO __CLRW1SX MOVW R30,R28 SUBI R30,LOW(-@0) SBCI R31,HIGH(-@0) CLR R0 ST Z+,R0 ST Z,R0 .ENDM .MACRO __CLRD1SX MOVW R30,R28 SUBI R30,LOW(-@0) SBCI R31,HIGH(-@0) CLR R0 ST Z+,R0 ST Z+,R0 ST Z+,R0 ST Z,R0 .ENDM .MACRO __PUTB2SX MOVW R30,R28 SUBI R30,LOW(-@0) SBCI R31,HIGH(-@0) ST Z,R26 .ENDM .MACRO __PUTW2SX MOVW R30,R28 SUBI R30,LOW(-@0) SBCI R31,HIGH(-@0) ST Z+,R26 ST Z,R27 .ENDM .MACRO __PUTBSRX MOVW R30,R28 SUBI R30,LOW(-@0) SBCI R31,HIGH(-@0) ST Z,R@1 .ENDM .MACRO __PUTWSRX MOVW R30,R28 SUBI R30,LOW(-@2) SBCI R31,HIGH(-@2) ST Z+,R@0 ST Z,R@1 .ENDM .MACRO __PUTB1SNX MOVW R26,R28 SUBI R26,LOW(-@0) SBCI R27,HIGH(-@0) LD R0,X+ LD R27,X MOV R26,R0 SUBI R26,LOW(-@1) SBCI R27,HIGH(-@1) ST X,R30 .ENDM .MACRO __PUTW1SNX MOVW R26,R28 SUBI R26,LOW(-@0) SBCI R27,HIGH(-@0) LD R0,X+ LD R27,X MOV R26,R0 SUBI R26,LOW(-@1) SBCI R27,HIGH(-@1) ST X+,R30 ST X,R31 .ENDM .MACRO __PUTD1SNX MOVW R26,R28 SUBI R26,LOW(-@0) SBCI R27,HIGH(-@0) LD R0,X+ LD R27,X MOV R26,R0 SUBI R26,LOW(-@1) SBCI R27,HIGH(-@1) ST X+,R30 ST X+,R31 ST X+,R22 ST X,R23 .ENDM .MACRO __MULBRR MULS R@0,R@1 MOV R30,R0 .ENDM .MACRO __MULBRRU MUL R@0,R@1 MOV R30,R0 .ENDM .CSEG .ORG 0 .INCLUDE "source.vec" .INCLUDE "source.inc" __RESET: CLI CLR R30 OUT EECR,R30 ;INTERRUPT VECTORS ARE PLACED ;AT THE START OF FLASH LDI R31,1 OUT GICR,R31 OUT GICR,R30 OUT MCUCR,R30 ;DISABLE WATCHDOG LDI R31,0x18 OUT WDTCR,R31 OUT WDTCR,R30 ;CLEAR R2-R14 LDI R24,13 LDI R26,2 CLR R27 __CLEAR_REG: ST X+,R30 DEC R24 BRNE __CLEAR_REG ;CLEAR SRAM LDI R24,LOW(0x800) LDI R25,HIGH(0x800) LDI R26,0x60 __CLEAR_SRAM: ST X+,R30 SBIW R24,1 BRNE __CLEAR_SRAM ;GLOBAL VARIABLES INITIALIZATION LDI R30,LOW(__GLOBAL_INI_TBL*2) LDI R31,HIGH(__GLOBAL_INI_TBL*2) __GLOBAL_INI_NEXT: LPM R24,Z+ LPM R25,Z+ SBIW R24,0 BREQ __GLOBAL_INI_END LPM R26,Z+ LPM R27,Z+ LPM R0,Z+ LPM R1,Z+ MOVW R22,R30 MOVW R30,R0 __GLOBAL_INI_LOOP: LPM R0,Z+ ST X+,R0 SBIW R24,1 BRNE __GLOBAL_INI_LOOP MOVW R30,R22 RJMP __GLOBAL_INI_NEXT __GLOBAL_INI_END: ;STACK POINTER INITIALIZATION LDI R30,LOW(0x85F) OUT SPL,R30 LDI R30,HIGH(0x85F) OUT SPH,R30 ;DATA STACK POINTER INITIALIZATION LDI R28,LOW(0x260) LDI R29,HIGH(0x260) JMP _main .ESEG .ORG 0 .DSEG .ORG 0x260 ; 1 /*********************************************************** ; 2 ***** ECE 476 Spring 2004 Final Project ******* ; 3 ***** The "Sober Up!" Breath-o-Matic Alcohol Sensor ******* ; 4 ***** ******* ; 5 ***** By Dan Golden and Alex Averbukh ******* ; 6 ***** 04/09/2004 ******* ; 7 ***********************************************************/ ; 8 ; 9 /************************************ ; 10 ***** Port Description ******* ; 11 ************************************ ; 12 ; 13 A.0 Alcohol Sensor ; 14 A.1 Pressure Sensor (Diff Amp output) ; 15 A[2:7] NOT USED ; 16 B.0 Keyboard Clock ; 17 B.1 Power ; 18 B.3 Power button ; 19 B.3 NOT USED ; 20 B[4:5] Breathing LEDs [Red Green] ; 21 B[6:7] Buttons [Blue Green] ; 22 C[0:7] LCD ; 23 D.0 Keyboard Data ; 24 D[1:6] ETOH LEDs ; 25 D.7 Speaker ; 26 */ ; 27 ; 28 /************************************ ; 29 ***** Includes ******* ; 30 ************************************/ ; 31 ; 32 #include ; 33 #include ; 34 #include ; 35 #include ; 36 #include ; 37 ; 38 /************************************* ; 39 ***** Definitions ******* ; 40 *************************************/ ; 41 ; 42 #define VCC 4.86 ; 43 #define R0 6584 ; 44 #define R1 1970 ; 45 #define numkbdCodes 39 ; 46 #define hsnamelength 12 ; 47 #define numsamples 10 ; 48 ; 49 // broken pressure gradient ; 50 #define bpg 0.30 ; 51 ; 52 // MainState Definitions ; 53 #define WarmingUp 0 ; 54 #define MainMenu 1 ; 55 #define TakingSample 2 ; 56 #define EnteringHighScore 3 ; 57 #define HighScoreList 4 ; 58 ; 59 // Port Definitions ; 60 #define bLEDr PORTB.4 ; 61 #define bLEDg PORTB.5 ; 62 #define bluebutton PINB.6 ; 63 #define greenbutton PINB.7 ; 64 #define ETOHLED1 PORTD.1 // g ; 65 #define ETOHLED2 PORTD.2 // g ; 66 #define ETOHLED3 PORTD.3 // y ; 67 #define ETOHLED4 PORTD.4 // y ; 68 #define ETOHLED5 PORTD.5 // r ; 69 #define ETOHLED6 PORTD.6 // r ; 70 ; 71 // ETOH level definitions ; 72 // Given values are the MAX BACs for each level ; 73 #define sober 0.04 ; 74 #define happy 0.06 ; 75 #define confused 0.09 ; 76 #define tipsy 0.12 ; 77 #define incomprehensible 0.15 ; 78 #define borisyeltsin ; 79 ; 80 /************************************* ; 81 ***** LCD Initialization ******* ; 82 *************************************/ ; 83 #define LCDwidth 16 //characters ; 84 // LCD is on PORT C ; 85 #asm ; 86 .equ __lcd_port=0x15 .equ __lcd_port=0x15 ; 87 #endasm ; 88 #include // LCD driver routines ; 89 ; 90 /************************************* ; 91 ***** Global Variables ******* ; 92 *************************************/ ; 93 ; 94 unsigned int ms = 0, tempcount = 0; ; 95 unsigned char MainState, TestBreathState, EnterHighScoreState, HighScoreState; ; 96 unsigned char ButtonState; ; 97 unsigned char bluebuttonPressed, greenbuttonPressed; ; 98 unsigned char buttonsPressed; _buttonsPressed: .BYTE 0x1 ; 99 unsigned char thishighscorename[hsnamelength+1]; // 12 chars + null _thishighscorename: .BYTE 0xD ; 100 unsigned char thishighscore; _thishighscore: .BYTE 0x1 ; 101 float BAC; _BAC: .BYTE 0x4 ; 102 float thispressure, lastpressure; _thispressure: .BYTE 0x4 _lastpressure: .BYTE 0x4 ; 103 float voltage, tempfloat; _voltage: .BYTE 0x4 _tempfloat: .BYTE 0x4 ; 104 float BAC_samples[30]; _BAC_samples: .BYTE 0x78 ; 105 char count = 0, count2 = 0; _count: .BYTE 0x1 _count2: .BYTE 0x1 ; 106 ; 107 // High Scores ; 108 unsigned char highscorenames[10][hsnamelength+1]; _highscorenames: .BYTE 0x82 ; 109 float highscores[10]; _highscores: .BYTE 0x28 ; 110 unsigned char numhighscores = 0; _numhighscores: .BYTE 0x1 ; 111 ; 112 // SCANCODES ; 113 unsigned char kbdCodes[]={0x1C,0x32,0x21,0x23,0x24,0x2B,0x34,0x33, _kbdCodes: ; 114 0x43,0x3B,0x42,0x4B,0x3A,0x31,0x44,0x4D, ; 115 0x15,0x2D,0x1B,0x2C,0x3C,0x2A,0x1D,0x22, ; 116 0x35,0x1A,0x45,0x16,0x1E,0x26,0x25,0x2E, ; 117 0x36,0x3D,0x3E,0x46,0x29,0x66,0x5A}; .BYTE 0x27 ; 118 // letters, numbers,space,backspace,ENTER ; 119 ; 120 //kbd2ascii ; 121 unsigned char code; _code: .BYTE 0x1 ; 122 bit throw=0; ; 123 int i; _i: .BYTE 0x2 ; 124 ; 125 //UART ; 126 unsigned char char_count; _char_count: .BYTE 0x1 ; 127 bit cmd_ready; ; 128 char kbd_str[20]; _kbd_str: .BYTE 0x14 ; 129 unsigned char c; _c: .BYTE 0x1 ; 130 ; 131 //lcd ; 132 char lcd_buffer[17]; _lcd_buffer: .BYTE 0x11 ; 133 ; 134 /************************************* ; 135 ***** Function Prototypes ******* ; 136 *************************************/ ; 137 ; 138 void initialize(void); ; 139 ; 140 // state machines ; 141 void MainStateMachine(void); ; 142 void TestBreathStateMachine(void); ; 143 void EnterHighScoreStateMachine(void); ; 144 void HighScoreStateMachine(void); ; 145 void ButtonStateMachine(void); ; 146 ; 147 void DeleteHighScores(void); ; 148 ; 149 // change ADC channel - 0:ETOH, 1:Pressure ; 150 void ADC_channel(unsigned char); ; 151 ; 152 // puts MCU to sleep to get a measurement from ADC & returns voltage ; 153 float ADC_measure(void); ; 154 ; 155 // returns BAC from ETOH PPM measurement ; 156 float PPMtoBAC(float); ; 157 ; 158 // returns character corresponding to the scancode of keyboard ; 159 unsigned char kbd2ascii(void); ; 160 ; 161 //initializes UART for receive ; 162 void UARTInit(void); ; 163 ; 164 // convert ETOH sensor voltage to BAC ; 165 float VstoBAC(float); ; 166 ; 167 // make speaker noises during and after breath sample ; 168 void Speaker(unsigned char); ; 169 void ETOHLevelOutput(unsigned char); ; 170 ; 171 // turn off LEDs ; 172 void LEDsoff(void); ; 173 ; 174 // Wait 6 seconds for sensor reading to stabalize; return value = BAC ; 175 float ETOHStabalize(void); ; 176 ; 177 /************************************* ; 178 ***** Interrupts ******* ; 179 *************************************/ ; 180 ; 181 interrupt [TIM0_COMP] void timer0_compare(void) ; 182 { .CSEG _timer0_compare: CALL SUBOPT_0x0 ; 183 // millisecond timers ; 184 ms++; LDI R30,LOW(1) LDI R31,HIGH(1) __ADDWRR 4,5,30,31 ; 185 tempcount++; __ADDWRR 6,7,30,31 ; 186 ; 187 if ((ms & 31) == 0) // every 32 ms, run button state machine MOV R30,R4 ANDI R30,LOW(0x1F) BRNE _0x4 ; 188 ButtonStateMachine(); RCALL _ButtonStateMachine ; 189 } _0x4: CALL SUBOPT_0x1 RETI ; 190 ; 191 /***************************************************/ ; 192 interrupt [USART_RXC] void uartreceive(void) ; 193 { _uartreceive: CALL SUBOPT_0x0 ; 194 code = UDR; // get character from UART IN R30,0xC STS _code,R30 ; 195 c = kbd2ascii(); RCALL _kbd2ascii STS _c,R30 ; 196 if(c != 0) CPI R30,0 BREQ _0x5 ; 197 { ; 198 // if character is not return or backspace... ; 199 if (c != '\r' && c != '\b' ) LDS R26,_c CPI R26,LOW(0xD) BREQ _0x7 CPI R26,LOW(0x8) BRNE _0x8 _0x7: RJMP _0x6 _0x8: ; 200 { ; 201 // if the name is not too long... ; 202 if(char_count < hsnamelength) LDS R26,_char_count CPI R26,LOW(0xC) BRSH _0x9 ; 203 { ; 204 kbd_str[char_count++] = c; LDS R30,_char_count SUBI R30,-LOW(1) STS _char_count,R30 SUBI R30,LOW(1) LDI R31,0 SUBI R30,LOW(-_kbd_str) SBCI R31,HIGH(-_kbd_str) MOVW R26,R30 LDS R30,_c ST X,R30 ; 205 kbd_str[char_count] = 0; //legal C string CALL SUBOPT_0x2 ; 206 } ; 207 } _0x9: ; 208 // if character is backspace... ; 209 else if(c == '\b') RJMP _0xA _0x6: LDS R26,_c CPI R26,LOW(0x8) BRNE _0xB ; 210 { ; 211 // and the name has a positive length... ; 212 if(char_count > 0) LDS R26,_char_count LDI R30,LOW(0) CP R30,R26 BRSH _0xC ; 213 { ; 214 //lcd_clear(); ; 215 //kbd_str[--char_count] = 0; ; 216 kbd_str[--char_count] = ' '; LDS R30,_char_count SUBI R30,LOW(1) STS _char_count,R30 LDI R31,0 SUBI R30,LOW(-_kbd_str) SBCI R31,HIGH(-_kbd_str) MOVW R26,R30 LDI R30,LOW(32) ST X,R30 ; 217 } ; 218 } _0xC: ; 219 // if character is return... ; 220 else RJMP _0xD _0xB: ; 221 { ; 222 kbd_str[char_count] = 0; // end string in a happy C way CALL SUBOPT_0x2 ; 223 cmd_ready = 1; // command is ready to be executed SET BLD R2,1 ; 224 } _0xD: _0xA: ; 225 } ; 226 } _0x5: CALL SUBOPT_0x1 RETI ; 227 ; 228 // this interrupt exists to wake the CPU from ADC sleep mode ; 229 interrupt [ADC_INT] void ADCconvcompl(void) ; 230 { _ADCconvcompl: ; 231 } RETI ; 232 ; 233 /************************************* ; 234 ****** Main ******* ; 235 *************************************/ ; 236 ; 237 void main(void) ; 238 { _main: ; 239 ; 240 initialize(); RCALL _initialize ; 241 ; 242 // get initial pressure ; 243 ADC_channel(1); CALL SUBOPT_0x3 ; 244 lastpressure = ADC_measure(); ; 245 thispressure = lastpressure; ; 246 ; 247 // used to toggle LCD messages ; 248 tempcount=0; ; 249 ; 250 while(1) _0xE: ; 251 { ; 252 MainStateMachine(); RCALL _MainStateMachine ; 253 } RJMP _0xE ; 254 } _0x11: RJMP _0x11 ; 255 ; 256 /************************************* ; 257 ***** Function Definitions ******* ; 258 *************************************/ ; 259 ; 260 void initialize(void) ; 261 { _initialize: ; 262 ; 263 // set initial variables to 0 ; 264 voltage = 0; __GETD1N 0x0 STS _voltage,R30 STS _voltage+1,R31 STS _voltage+2,R22 STS _voltage+3,R23 ; 265 MainState = MainMenu; LDI R30,LOW(1) MOV R8,R30 ; 266 TestBreathState = 0; CLR R9 ; 267 EnterHighScoreState = 0; CLR R10 ; 268 HighScoreState = 0; CLR R11 ; 269 ButtonState = 0; CLR R12 ; 270 bluebuttonPressed = 0; CLR R13 ; 271 greenbuttonPressed = 0; CLR R14 ; 272 buttonsPressed = 0; LDI R30,LOW(0) STS _buttonsPressed,R30 ; 273 ms = 0; CLR R4 CLR R5 ; 274 ; 275 // initialize UART ; 276 UARTInit(); RCALL _UARTInit ; 277 ; 278 // initialize timers ; 279 ; 280 // Timer 0 is a ms timer ; 281 TIMSK=2; //turn on timer 0 cmp match ISR LDI R30,LOW(2) OUT 0x39,R30 ; 282 OCR0 = 249; //set the compare register to 250 time ticks LDI R30,LOW(249) OUT 0x3C,R30 ; 283 TCCR0=0b00001011; //prescalar to 64 and turn on clear-on-match LDI R30,LOW(11) OUT 0x33,R30 ; 284 ; 285 // Timer 2 is speaker output ; 286 // FOC off, CTC, OC2 off, CLK/128 ; 287 TCCR2 = 0b00001110; LDI R30,LOW(14) OUT 0x25,R30 ; 288 ; 289 // initialize ADC ; 290 ADMUX = 0b01100000; // reference VCC, channel 0, left adjust LDI R30,LOW(96) OUT 0x7,R30 ; 291 ; 292 // ADC enable, start conversion, interrupt disable, CLK/128 ; 293 ADCSRA = 0b11001111; LDI R30,LOW(207) OUT 0x6,R30 ; 294 ; 295 // initialize sleep mode ; 296 MCUCR = 0b10010000; // enable ADC sleep mode LDI R30,LOW(144) OUT 0x35,R30 ; 297 ; 298 // initialize ports ; 299 ; 300 DDRA = 0b00000000; LDI R30,LOW(0) OUT 0x1A,R30 ; 301 /* [7:2] Not Used ; 302 1: Pressure ADC input ; 303 0: ETOH ADC input ; 304 */ ; 305 PORTA = 0b00000000; // No pullups OUT 0x1B,R30 ; 306 ; 307 DDRB = 0b00110010; LDI R30,LOW(50) OUT 0x17,R30 ; 308 /* 7: Green button ; 309 6: Blue button ; 310 5: Green breathing LED ; 311 4: Red breathing LED ; 312 3: Not Used ; 313 2: Not Used ; 314 1: Circuit enable (1 = on) ; 315 0: Keyboard clock ; 316 */ ; 317 PORTB = 0b00000010; // circuit on, breathing LEDs off, no pullups LDI R30,LOW(2) OUT 0x18,R30 ; 318 ; 319 // PORT C is LCD ; 320 ; 321 DDRD = 0b11111110; // RXD input,output ETOH LEDs,output speaker LDI R30,LOW(254) OUT 0x11,R30 ; 322 /* 7: Speaker ; 323 6: ETOH LED 6 (r) ; 324 5: ETOH LED 5 (r) ; 325 4: ETOH LED 4 (y) ; 326 3: ETOH LED 3 (y) ; 327 2: ETOH LED 2 (g) ; 328 1: ETOH LED 1 (g) ; 329 0: Keyboard data ; 330 */ ; 331 PORTD = 0b10000000; // All off, no pullups LDI R30,LOW(128) OUT 0x12,R30 ; 332 ; 333 // initialize LCD, display welcome message ; 334 lcd_init(LCDwidth); LDI R30,LOW(16) ST -Y,R30 CALL _lcd_init ; 335 lcd_clear(); CALL SUBOPT_0x4 ; 336 lcd_gotoxy(0,0); ; 337 lcd_putsf("Welcome to the"); __POINTW1FN _0,0 CALL SUBOPT_0x5 ; 338 lcd_gotoxy(0,1); CALL SUBOPT_0x6 ; 339 lcd_putsf("Breath-o-Matic!"); __POINTW1FN _0,15 CALL SUBOPT_0x7 ; 340 delay_ms(2000); ; 341 ; 342 lcd_clear(); CALL _lcd_clear ; 343 ; 344 // turn on interrupts ; 345 #asm("sei"); sei ; 346 } RET ; 347 ; 348 void ADC_channel(unsigned char channel) // 0: ETOH, 1: Pressure ; 349 { _ADC_channel: ; 350 ADMUX = 0b01100000 | channel; // set channel LD R30,Y ORI R30,LOW(0x60) OUT 0x7,R30 ; 351 ADCSRA = ADCSRA | 0b01000000; // start conversion SBI 0x6,6 ; 352 } ADIW R28,1 RET ; 353 ; 354 float ADC_measure(void) ; 355 { _ADC_measure: ; 356 #asm("sleep"); // sleep to start conversion sleep ; 357 return((float) (ADCH / 256.0 * VCC)); // convert to voltage IN R30,0x5 MOVW R26,R30 MOVW R24,R22 CLR R27 CLR R24 CLR R25 CALL __CDF2 __GETD1N 0x43800000 CALL __DIVF21 __GETD2N 0x409B851F CALL __MULF12 RET ; 358 } ; 359 ; 360 float PPMtoBAC(float PPM) ; 361 { _PPMtoBAC: ; 362 /* ; 363 BAC of 0.01 equals 0.01g ETOH in 210 L air ; 364 PPM is g ETOH for every 10^6 g Air ; 365 At STP, air has a density of 1.29 g/L ; 366 thus BAC = (g ETOH) / (10^6 g Air) * (1.29 g Air / L air) * 210 * 10^-6 ; 367 */ ; 368 ; 369 return (PPM * 1.29 * 210 / 1000000); __GETD2S 0 __GETD1N 0x3FA51EB8 CALL __MULF12 __GETD2N 0x43520000 CALL __MULF12 MOVW R26,R30 MOVW R24,R22 __GETD1N 0x49742400 CALL __DIVF21 ADIW R28,4 RET ; 370 } ; 371 ; 372 float VstoBAC(float Vs) ; 373 { _VstoBAC: ; 374 float Rs, PPM; ; 375 /* ; 376 VCC - ETOH sensor - 2k resistor - GND ; 377 Measuring volage Vs between ETOH sensor and 2k resistor ; 378 Rs = Rl*(VCC/Vs - 1) ; 379 Region 1 (2 <= Rs/R0 < 4): PPM = 244.8 * (R0/Rs)^1.304 ; 380 Region 2 (Rs/R0 < 2): PPM = 248 * ((R0/Rs)^1.323 ; 381 */ ; 382 ; 383 // Region 1 readings have been experimentally determined to be junk! ; 384 ; 385 Rs = R1 * (VCC / Vs - 1); SBIW R28,8 ; Vs -> Y+8 ; Rs -> Y+4 ; PPM -> Y+0 __GETD1S 8 __GETD2N 0x409B851F CALL __DIVF21 MOVW R26,R30 MOVW R24,R22 CALL SUBOPT_0x8 __GETD2N 0x44F64000 CALL __MULF12 __PUTD1S 4 ; 386 if (Rs/R0 < 2) // Region 2 __GETD2S 4 __GETD1N 0x45CDC000 CALL __DIVF21 MOVW R26,R30 MOVW R24,R22 __GETD1N 0x40000000 CALL __CMPF12 BRSH _0x12 ; 387 PPM = 248 * pow((R0/Rs), 1.323); __GETD1S 4 __GETD2N 0x45CDC000 CALL __DIVF21 CALL __PUTPARD1 __GETD1N 0x3FA95810 CALL __PUTPARD1 CALL _pow __GETD2N 0x43780000 CALL __MULF12 __PUTD1S 0 ; 388 // else if (Rs/R0 < 4) // Region 1 ; 389 // PPM = 244.8 * pow((R0/Rs),1.304); ; 390 else RJMP _0x13 _0x12: ; 391 PPM = 0; __CLRD1S 0 ; 392 ; 393 return PPMtoBAC(PPM); _0x13: __GETD1S 0 CALL __PUTPARD1 CALL _PPMtoBAC ADIW R28,12 RET ; 394 } ; 395 ; 396 unsigned char kbd2ascii(void) ; 397 { _kbd2ascii: ; 398 /* ; 399 1) accept keyboard code ; 400 2) lookup ascii value ; 401 3) throw away F0 and following code ; 402 4) update the number of alpha-numeric characters. ; 403 */ ; 404 ; 405 if(code!=0xf0 && !throw) LDS R26,_code CPI R26,LOW(0xF0) BREQ _0x15 SBRS R2,0 RJMP _0x16 _0x15: RJMP _0x14 _0x16: ; 406 { ; 407 // search through the character code list for the received character ; 408 for(i=0; i= 0) LD R26,Y CPI R26,0 BRLO _0x2E ; 505 { ; 506 ETOHLED1 = 1; SBI 0x12,1 ; 507 OCR2 = 120; LDI R30,LOW(120) OUT 0x23,R30 ; 508 TCCR2 = TCCR2 | 0b00010000; CALL SUBOPT_0xC ; 509 delay_ms(100); CALL SUBOPT_0xD ; 510 TCCR2 = TCCR2 & 0b11101111; CALL SUBOPT_0xB ; 511 delay_ms(100); CALL SUBOPT_0xD ; 512 } ; 513 if (level >= 1) _0x2E: LD R26,Y CPI R26,LOW(0x1) BRLO _0x2F ; 514 { ; 515 ETOHLED2 = 1; SBI 0x12,2 ; 516 OCR2 = 110; LDI R30,LOW(110) OUT 0x23,R30 ; 517 TCCR2 = TCCR2 | 0b00010000; CALL SUBOPT_0xC ; 518 delay_ms(100); CALL SUBOPT_0xD ; 519 TCCR2 = TCCR2 & 0b11101111; CALL SUBOPT_0xB ; 520 delay_ms(100); CALL SUBOPT_0xD ; 521 } ; 522 if (level >= 2) _0x2F: LD R26,Y CPI R26,LOW(0x2) BRLO _0x30 ; 523 { ; 524 ETOHLED3 = 1; SBI 0x12,3 ; 525 OCR2 = 100; LDI R30,LOW(100) OUT 0x23,R30 ; 526 TCCR2 = TCCR2 | 0b00010000; CALL SUBOPT_0xC ; 527 delay_ms(100); CALL SUBOPT_0xD ; 528 TCCR2 = TCCR2 & 0b11101111; CALL SUBOPT_0xB ; 529 delay_ms(100); CALL SUBOPT_0xD ; 530 } ; 531 if (level >= 3) _0x30: LD R26,Y CPI R26,LOW(0x3) BRLO _0x31 ; 532 { ; 533 ETOHLED4 = 1; SBI 0x12,4 ; 534 OCR2 = 90; LDI R30,LOW(90) OUT 0x23,R30 ; 535 TCCR2 = TCCR2 | 0b00010000; CALL SUBOPT_0xC ; 536 delay_ms(100); CALL SUBOPT_0xD ; 537 TCCR2 = TCCR2 & 0b11101111; CALL SUBOPT_0xB ; 538 delay_ms(100); CALL SUBOPT_0xD ; 539 } ; 540 if (level >= 4) _0x31: LD R26,Y CPI R26,LOW(0x4) BRLO _0x32 ; 541 { ; 542 ETOHLED5 = 1; SBI 0x12,5 ; 543 OCR2 = 80; LDI R30,LOW(80) OUT 0x23,R30 ; 544 TCCR2 = TCCR2 | 0b00010000; CALL SUBOPT_0xC ; 545 delay_ms(100); CALL SUBOPT_0xD ; 546 TCCR2 = TCCR2 & 0b11101111; CALL SUBOPT_0xB ; 547 delay_ms(100); CALL SUBOPT_0xD ; 548 } ; 549 if (level >= 5) _0x32: LD R26,Y CPI R26,LOW(0x5) BRLO _0x33 ; 550 { ; 551 ETOHLED6 = 1; SBI 0x12,6 ; 552 OCR2 = 70; LDI R30,LOW(70) OUT 0x23,R30 ; 553 TCCR2 = TCCR2 | 0b00010000; CALL SUBOPT_0xC ; 554 delay_ms(100); CALL SUBOPT_0xD ; 555 TCCR2 = TCCR2 & 0b11101111; CALL SUBOPT_0xB ; 556 delay_ms(100); CALL SUBOPT_0xD ; 557 } ; 558 ; 559 // play two more notes, to sound more musical ; 560 ; 561 OCR2 -= 5; _0x33: CALL SUBOPT_0x10 ; 562 TCCR2 = TCCR2 | 0b00010000; ; 563 delay_ms(100); CALL SUBOPT_0xD ; 564 TCCR2 = TCCR2 & 0b11101111; CALL SUBOPT_0xB ; 565 delay_ms(100); CALL SUBOPT_0xD ; 566 ; 567 OCR2 -= 5; CALL SUBOPT_0x10 ; 568 TCCR2 = TCCR2 | 0b00010000; ; 569 delay_ms(200); LDI R30,LOW(200) LDI R31,HIGH(200) CALL SUBOPT_0xE ; 570 TCCR2 = TCCR2 & 0b11101111; ; 571 } _0x154: ADIW R28,1 RET ; 572 ; 573 void LEDsoff(void) ; 574 { _LEDsoff: ; 575 ETOHLED1 = 0; CBI 0x12,1 ; 576 ETOHLED2 = 0; CBI 0x12,2 ; 577 ETOHLED3 = 0; CBI 0x12,3 ; 578 ETOHLED4 = 0; CBI 0x12,4 ; 579 ETOHLED5 = 0; CBI 0x12,5 ; 580 ETOHLED6 = 0; CBI 0x12,6 ; 581 bLEDr = 0; CBI 0x18,4 ; 582 bLEDg = 0; CBI 0x18,5 ; 583 } RET ; 584 ; 585 float ETOHStabalize(void) ; 586 { _ETOHStabalize: ; 587 float ETOH3, ETOH2, ETOH1, result; ; 588 ; 589 lcd_clear(); SBIW R28,16 ; ETOH3 -> Y+12 ; ETOH2 -> Y+8 ; ETOH1 -> Y+4 ; result -> Y+0 CALL SUBOPT_0x4 ; 590 lcd_gotoxy(0,0); ; 591 lcd_putsf("Wait"); __POINTW1FN _0,31 CALL SUBOPT_0x5 ; 592 ADC_channel(0); CALL _ADC_channel ; 593 ETOH3 = ADC_measure(); // current measure CALL _ADC_measure __PUTD1S 12 ; 594 ETOH2 = -1; // one second ago __GETD1N 0xBF800000 __PUTD1S 8 ; 595 ETOH1 = -1; // two seconds ago __PUTD1S 4 ; 596 tempcount = 0; CALL SUBOPT_0x11 ; 597 count = 0; ; 598 ; 599 // wait six seconds, or until the sensor reading stabalizes, whichever is first ; 600 while ((tempcount < 6000) && !((ETOH1 < ETOH3 + 0.005) && (ETOH1 > ETOH3 - 0.005))) _0x34: LDI R30,LOW(6000) LDI R31,HIGH(6000) CP R6,R30 CPC R7,R31 BRSH _0x37 __GETD1S 12 __GETD2N 0x3BA3D70A CALL __ADDF12 __GETD2S 4 CALL __CMPF12 BRSH _0x38 __GETD2S 12 __GETD1N 0x3BA3D70A CALL __SWAPD12 CALL __SUBF12 __GETD2S 4 CALL __CMPF12 BREQ PC+2 BRCC PC+3 JMP _0x38 RJMP _0x37 _0x38: RJMP _0x3A _0x37: RJMP _0x36 _0x3A: ; 601 { ; 602 if ((tempcount & 1023) == 0) __GETW1R 6,7 ANDI R31,HIGH(0x3FF) SBIW R30,0 BREQ PC+3 JMP _0x3B ; 603 { ; 604 ETOH1 = ETOH2; __GETD1S 8 __PUTD1S 4 ; 605 ETOH2 = ETOH3; __GETD1S 12 __PUTD1S 8 ; 606 ETOH3 = VstoBAC(ADC_measure()); CALL _ADC_measure CALL __PUTPARD1 CALL _VstoBAC __PUTD1S 12 ; 607 ; 608 lcd_gotoxy(12,0); LDI R30,LOW(12) CALL SUBOPT_0x12 ; 609 sprintf(lcd_buffer, "%4.2f", ETOH3); // print current BAC __POINTW1FN _0,36 ST -Y,R31 ST -Y,R30 __GETD1S 16 CALL __PUTPARD1 LDI R24,4 CALL SUBOPT_0x13 ; 610 lcd_puts(lcd_buffer); ; 611 lcd_gotoxy(count,1); LDS R30,_count ST -Y,R30 CALL SUBOPT_0x6 ; 612 lcd_putsf("."); // put progress dots on screen __POINTW1FN _0,42 ST -Y,R31 ST -Y,R30 CALL _lcd_putsf ; 613 Speaker(4); // beep LDI R30,LOW(4) ST -Y,R30 CALL _Speaker ; 614 delay_ms(150); LDI R30,LOW(150) LDI R31,HIGH(150) ST -Y,R31 ST -Y,R30 CALL _delay_ms ; 615 Speaker(0); CALL SUBOPT_0x14 ; 616 count++; ; 617 } ; 618 } _0x3B: RJMP _0x34 _0x36: ; 619 if (tempcount == 6000) LDI R30,LOW(6000) LDI R31,HIGH(6000) CP R30,R6 CPC R31,R7 BRNE _0x3C ; 620 result = -1; // no stabalization; bad sample __GETD1N 0xBF800000 RJMP _0x155 ; 621 else _0x3C: ; 622 result = ETOH3; // good sample __GETD1S 12 _0x155: __PUTD1S 0 ; 623 ; 624 delay_ms(1000); CALL SUBOPT_0x15 ; 625 return result; __GETD1S 0 ADIW R28,16 RET ; 626 } ; 627 ; 628 void ButtonStateMachine(void) ; 629 { _ButtonStateMachine: ; 630 switch(ButtonState) MOV R30,R12 ; 631 { ; 632 case 0: // no press CPI R30,0 BRNE _0x41 ; 633 if (bluebutton || greenbutton) SBIC 0x16,6 RJMP _0x43 SBIS 0x16,7 RJMP _0x42 _0x43: ; 634 { ; 635 if (bluebutton) SBIS 0x16,6 RJMP _0x45 ; 636 buttonsPressed += 2; LDS R30,_buttonsPressed SUBI R30,-LOW(2) STS _buttonsPressed,R30 ; 637 else if (greenbutton) RJMP _0x46 _0x45: SBIS 0x16,7 RJMP _0x47 ; 638 buttonsPressed += 1; LDS R30,_buttonsPressed SUBI R30,-LOW(1) STS _buttonsPressed,R30 ; 639 ; 640 ButtonState = 1; _0x47: _0x46: LDI R30,LOW(1) MOV R12,R30 ; 641 } ; 642 break; _0x42: RJMP _0x40 ; 643 ; 644 case 1: // maybe press _0x41: CPI R30,LOW(0x1) BRNE _0x48 ; 645 ButtonState = 2; LDI R30,LOW(2) MOV R12,R30 ; 646 ; 647 if (bluebutton && (buttonsPressed & 0x02)) SBIS 0x16,6 RJMP _0x4A LDS R30,_buttonsPressed ANDI R30,LOW(0x2) BRNE _0x4B _0x4A: RJMP _0x49 _0x4B: ; 648 { ; 649 bluebuttonPressed = 1; LDI R30,LOW(1) MOV R13,R30 ; 650 } ; 651 else if (greenbutton && (buttonsPressed & 0x01)) RJMP _0x4C _0x49: SBIS 0x16,7 RJMP _0x4E LDS R30,_buttonsPressed ANDI R30,LOW(0x1) BRNE _0x4F _0x4E: RJMP _0x4D _0x4F: ; 652 { ; 653 greenbuttonPressed = 1; LDI R30,LOW(1) MOV R14,R30 ; 654 } ; 655 else RJMP _0x50 _0x4D: ; 656 { ; 657 ButtonState = 0; CLR R12 ; 658 } _0x50: _0x4C: ; 659 break; RJMP _0x40 ; 660 ; 661 case 2: // press _0x48: CPI R30,LOW(0x2) BRNE _0x51 ; 662 if (!(bluebutton || greenbutton)) SBIC 0x16,6 RJMP _0x53 SBIS 0x16,7 RJMP _0x54 _0x53: RJMP _0x52 _0x54: ; 663 ButtonState = 3; LDI R30,LOW(3) MOV R12,R30 ; 664 break; _0x52: RJMP _0x40 ; 665 ; 666 case 3: // maybe no press _0x51: CPI R30,LOW(0x3) BRNE _0x5A ; 667 if (!(bluebutton || greenbutton)) SBIC 0x16,6 RJMP _0x57 SBIS 0x16,7 RJMP _0x58 _0x57: RJMP _0x56 _0x58: ; 668 { ; 669 buttonsPressed = 0; LDI R30,LOW(0) STS _buttonsPressed,R30 ; 670 greenbuttonPressed = 0; CLR R14 ; 671 bluebuttonPressed = 0; CLR R13 ; 672 ButtonState = 0; CLR R12 ; 673 } ; 674 else RJMP _0x59 _0x56: ; 675 ButtonState = 2; LDI R30,LOW(2) MOV R12,R30 ; 676 break; _0x59: RJMP _0x40 ; 677 ; 678 default: // uh oh _0x5A: ; 679 ButtonState = 0; CLR R12 ; 680 } _0x40: ; 681 } RET ; 682 ; 683 void TestBreathStateMachine(void) ; 684 { _TestBreathStateMachine: ; 685 // INITIAL PRECONDITION: tempcount = 0; count = 0; TestBreathState = 0; ; 686 switch (TestBreathState) MOV R30,R9 ; 687 { ; 688 case 0: // breathing CPI R30,0 BREQ PC+3 JMP _0x5E ; 689 // every ~1/2 second... ; 690 if (((tempcount & 511) == 0) && (count < numsamples)) CALL SUBOPT_0x16 BRNE _0x60 LDS R26,_count CPI R26,LOW(0xA) BRLO _0x61 _0x60: RJMP _0x5F _0x61: ; 691 { ; 692 ADC_channel(0); // ETOH channel LDI R30,LOW(0) ST -Y,R30 CALL _ADC_channel ; 693 BAC_samples[count] = ADC_measure(); CALL SUBOPT_0x17 ADD R30,R26 ADC R31,R27 PUSH R31 PUSH R30 CALL _ADC_measure POP R26 POP R27 CALL __PUTDP1 ; 694 ; 695 // display current voltage ; 696 lcd_gotoxy(9,1); LDI R30,LOW(9) ST -Y,R30 CALL SUBOPT_0x6 ; 697 sprintf(lcd_buffer,"%5.3f",BAC_samples[count]); LDI R30,LOW(_lcd_buffer) LDI R31,HIGH(_lcd_buffer) ST -Y,R31 ST -Y,R30 __POINTW1FN _0,44 ST -Y,R31 ST -Y,R30 CALL SUBOPT_0x17 CALL SUBOPT_0x18 LDI R24,4 CALL SUBOPT_0x13 ; 698 lcd_puts(lcd_buffer); ; 699 ; 700 // beep, blink red LED ; 701 Speaker(1); LDI R30,LOW(1) ST -Y,R30 CALL _Speaker ; 702 delay_ms(100); CALL SUBOPT_0xD ; 703 Speaker(0); CALL SUBOPT_0x14 ; 704 count++; ; 705 ; 706 // print seconds to LCD ; 707 if (count & 1) // every second LDS R30,_count ANDI R30,LOW(0x1) BREQ _0x62 ; 708 { ; 709 lcd_gotoxy((count >> 1),1); LDS R30,_count LSR R30 ST -Y,R30 CALL SUBOPT_0x6 ; 710 sprintf(lcd_buffer, "%d", (count >> 1)+1); LDI R30,LOW(_lcd_buffer) LDI R31,HIGH(_lcd_buffer) ST -Y,R31 ST -Y,R30 __POINTW1FN _0,50 ST -Y,R31 ST -Y,R30 LDS R30,_count LSR R30 CALL SUBOPT_0x19 LDI R24,4 CALL SUBOPT_0x13 ; 711 lcd_puts(lcd_buffer); ; 712 } ; 713 } _0x62: ; 714 else if (count >= numsamples) RJMP _0x63 _0x5F: LDS R26,_count CPI R26,LOW(0xA) BRLO _0x64 ; 715 TestBreathState = 1; // determine goodness of sample LDI R30,LOW(1) MOV R9,R30 ; 716 break; _0x64: _0x63: RJMP _0x5D ; 717 ; 718 case 1: // determine goodness of sample _0x5E: CPI R30,LOW(0x1) BREQ PC+3 JMP _0x65 ; 719 ; 720 // make good sound, light green LED ; 721 delay_ms(250); LDI R30,LOW(250) LDI R31,HIGH(250) ST -Y,R31 ST -Y,R30 CALL _delay_ms ; 722 Speaker(3); LDI R30,LOW(3) ST -Y,R30 CALL _Speaker ; 723 delay_ms(1000); CALL SUBOPT_0x15 ; 724 ; 725 BAC = ETOHStabalize(); CALL _ETOHStabalize STS _BAC,R30 STS _BAC+1,R31 STS _BAC+2,R22 STS _BAC+3,R23 ; 726 ; 727 if (BAC >= 0) // good sample LDS R26,_BAC LDS R27,_BAC+1 LDS R24,_BAC+2 LDS R25,_BAC+3 CALL __CPD20 BRGE PC+3 JMP _0x66 ; 728 { ; 729 ; 730 TestBreathState = 2; LDI R30,LOW(2) MOV R9,R30 ; 731 ; 732 // Light appropriate amount of LEDs ; 733 if (BAC < sober) __GETD1N 0x3D23D70A CALL __CMPF12 BRSH _0x67 ; 734 ETOHLevelOutput(0); LDI R30,LOW(0) ST -Y,R30 CALL _ETOHLevelOutput ; 735 else if (BAC < happy) RJMP _0x68 _0x67: LDS R26,_BAC LDS R27,_BAC+1 LDS R24,_BAC+2 LDS R25,_BAC+3 __GETD1N 0x3D75C28F CALL __CMPF12 BRSH _0x69 ; 736 ETOHLevelOutput(1); LDI R30,LOW(1) ST -Y,R30 CALL _ETOHLevelOutput ; 737 else if (BAC < confused) RJMP _0x6A _0x69: LDS R26,_BAC LDS R27,_BAC+1 LDS R24,_BAC+2 LDS R25,_BAC+3 __GETD1N 0x3DB851EC CALL __CMPF12 BRSH _0x6B ; 738 ETOHLevelOutput(2); LDI R30,LOW(2) ST -Y,R30 CALL _ETOHLevelOutput ; 739 else if (BAC < tipsy) RJMP _0x6C _0x6B: LDS R26,_BAC LDS R27,_BAC+1 LDS R24,_BAC+2 LDS R25,_BAC+3 __GETD1N 0x3DF5C28F CALL __CMPF12 BRSH _0x6D ; 740 ETOHLevelOutput(3); LDI R30,LOW(3) ST -Y,R30 CALL _ETOHLevelOutput ; 741 else if (BAC < incomprehensible) RJMP _0x6E _0x6D: LDS R26,_BAC LDS R27,_BAC+1 LDS R24,_BAC+2 LDS R25,_BAC+3 __GETD1N 0x3E19999A CALL __CMPF12 BRSH _0x6F ; 742 ETOHLevelOutput(4); LDI R30,LOW(4) RJMP _0x156 ; 743 else _0x6F: ; 744 ETOHLevelOutput(5); LDI R30,LOW(5) _0x156: ST -Y,R30 CALL _ETOHLevelOutput ; 745 ; 746 lcd_clear(); _0x6E: _0x6C: _0x6A: _0x68: CALL SUBOPT_0x4 ; 747 lcd_gotoxy(0,0); ; 748 sprintf(lcd_buffer, "BAC: %5.3f", BAC); // display BAC LDI R30,LOW(_lcd_buffer) LDI R31,HIGH(_lcd_buffer) ST -Y,R31 ST -Y,R30 __POINTW1FN _0,53 ST -Y,R31 ST -Y,R30 LDS R30,_BAC LDS R31,_BAC+1 LDS R22,_BAC+2 LDS R23,_BAC+3 CALL __PUTPARD1 LDI R24,4 CALL SUBOPT_0x13 ; 749 lcd_puts(lcd_buffer); ; 750 lcd_gotoxy(0,1); CALL SUBOPT_0x1A ; 751 lcd_putsf("G: Continue"); __POINTW1FN _0,64 ST -Y,R31 ST -Y,R30 CALL _lcd_putsf ; 752 ; 753 } ; 754 else // bad sample RJMP _0x71 _0x66: ; 755 { ; 756 // make bad sound, light red LED ; 757 Speaker(2); LDI R30,LOW(2) ST -Y,R30 CALL _Speaker ; 758 TestBreathState = 4; LDI R30,LOW(4) MOV R9,R30 ; 759 } _0x71: ; 760 ; 761 break; RJMP _0x5D ; 762 ; 763 case 2: // consistent samples _0x65: CPI R30,LOW(0x2) BRNE _0x72 ; 764 ; 765 // if drunky presses the green button... ; 766 if (greenbuttonPressed) TST R14 BREQ _0x73 ; 767 { ; 768 LEDsoff(); CALL _LEDsoff ; 769 while(greenbuttonPressed); // wait for release _0x74: TST R14 BRNE _0x74 ; 770 ; 771 ; 772 for (count = 0; count < numhighscores; count++) LDI R30,LOW(0) STS _count,R30 _0x78: LDS R30,_numhighscores LDS R26,_count CP R26,R30 BRSH _0x79 ; 773 // determine if this high score beats a current one ; 774 { ; 775 if (BAC > highscores[count]) // high score! CALL SUBOPT_0x1B LDS R26,_BAC LDS R27,_BAC+1 LDS R24,_BAC+2 LDS R25,_BAC+3 CALL __CMPF12 BREQ PC+2 BRCC PC+3 JMP _0x7A ; 776 { ; 777 MainState = EnteringHighScore; CALL SUBOPT_0x1C ; 778 EnterHighScoreState = 0; ; 779 thishighscore = count; LDS R30,_count CALL SUBOPT_0x1D ; 780 UCSRB = 0b10010000; // enable keyboard ; 781 tempcount = 0; // used to toggle LCD ; 782 break; RJMP _0x79 ; 783 } ; 784 } _0x7A: CALL SUBOPT_0x1E RJMP _0x78 _0x79: ; 785 ; 786 if ((numhighscores < 10) && (count == numhighscores)) LDS R26,_numhighscores CPI R26,LOW(0xA) BRSH _0x7C CALL SUBOPT_0x1F BREQ _0x7D _0x7C: RJMP _0x7B _0x7D: ; 787 // this is the lowest high score ; 788 { ; 789 MainState = EnteringHighScore; CALL SUBOPT_0x1C ; 790 EnterHighScoreState = 0; ; 791 thishighscore = numhighscores; LDS R30,_numhighscores CALL SUBOPT_0x1D ; 792 UCSRB = 0b10010000; // enable keyboard ; 793 tempcount = 0; // used to toggle LCD ; 794 } ; 795 else if (count == numhighscores) RJMP _0x7E _0x7B: CALL SUBOPT_0x1F BRNE _0x7F ; 796 // no high score :( ; 797 { ; 798 MainState = HighScoreList; CALL SUBOPT_0x20 ; 799 HighScoreState = 0; ; 800 tempcount = 0; // used to toggle LCD ; 801 } ; 802 } _0x7F: _0x7E: ; 803 ; 804 break; _0x73: RJMP _0x5D ; 805 ; 806 case 4: // inconsistent samples _0x72: CPI R30,LOW(0x4) BRNE _0x81 ; 807 LEDsoff(); CALL _LEDsoff ; 808 ; 809 lcd_clear(); CALL SUBOPT_0x4 ; 810 lcd_gotoxy(0,0); ; 811 lcd_putsf("Bad Sample!"); __POINTW1FN _0,76 ST -Y,R31 ST -Y,R30 CALL _lcd_putsf ; 812 delay_ms(3000); LDI R30,LOW(3000) LDI R31,HIGH(3000) ST -Y,R31 ST -Y,R30 CALL _delay_ms ; 813 ; 814 lcd_clear(); CALL SUBOPT_0x4 ; 815 lcd_gotoxy(0,0); ; 816 lcd_putsf("Returning to"); __POINTW1FN _0,88 CALL SUBOPT_0x5 ; 817 lcd_gotoxy(0,1); CALL SUBOPT_0x6 ; 818 lcd_putsf("Main Menu."); __POINTW1FN _0,101 CALL SUBOPT_0x7 ; 819 delay_ms(2000); ; 820 ; 821 // turn off red LED ; 822 bLEDr = 0; CBI 0x18,4 ; 823 ; 824 MainState = MainMenu; // back to Main Menu LDI R30,LOW(1) MOV R8,R30 ; 825 ; 826 // get initial pressure ; 827 lastpressure = ADC_measure(); CALL _ADC_measure STS _lastpressure,R30 STS _lastpressure+1,R31 STS _lastpressure+2,R22 STS _lastpressure+3,R23 ; 828 thispressure = lastpressure; STS _thispressure,R30 STS _thispressure+1,R31 STS _thispressure+2,R22 STS _thispressure+3,R23 ; 829 ; 830 tempcount = 0; CLR R6 CLR R7 ; 831 break; RJMP _0x5D ; 832 ; 833 default: _0x81: ; 834 TestBreathState = 0; CLR R9 ; 835 } _0x5D: ; 836 } RET ; 837 ; 838 void EnterHighScoreStateMachine(void) ; 839 { _EnterHighScoreStateMachine: ; 840 // INITIAL PRECONDITION: EnterHighScoreState = 0; tempcount = 0; ; 841 switch(EnterHighScoreState) MOV R30,R10 ; 842 { ; 843 case 0: // happy messages CPI R30,0 BREQ PC+3 JMP _0x85 ; 844 if (tempcount == 0) MOV R0,R6 OR R0,R7 BRNE _0x86 ; 845 { ; 846 lcd_clear(); CALL SUBOPT_0x4 ; 847 lcd_gotoxy(0,0); ; 848 lcd_putsf("You have a new"); __POINTW1FN _0,112 CALL SUBOPT_0x5 ; 849 lcd_gotoxy(0,1); CALL SUBOPT_0x6 ; 850 lcd_putsf("high score!"); __POINTW1FN _0,127 ST -Y,R31 ST -Y,R30 CALL _lcd_putsf ; 851 } ; 852 else if (tempcount == 2048) RJMP _0x87 _0x86: LDI R30,LOW(2048) LDI R31,HIGH(2048) CP R30,R6 CPC R31,R7 BRNE _0x88 ; 853 { ; 854 lcd_clear(); CALL SUBOPT_0x4 ; 855 lcd_gotoxy(0,0); ; 856 lcd_putsf("Enter your name"); __POINTW1FN _0,139 CALL SUBOPT_0x5 ; 857 lcd_gotoxy(0,1); CALL SUBOPT_0x6 ; 858 sprintf(lcd_buffer, "%d char max", hsnamelength); LDI R30,LOW(_lcd_buffer) LDI R31,HIGH(_lcd_buffer) ST -Y,R31 ST -Y,R30 __POINTW1FN _0,155 ST -Y,R31 ST -Y,R30 __GETD1N 0xC CALL __PUTPARD1 LDI R24,4 CALL SUBOPT_0x13 ; 859 lcd_puts(lcd_buffer); ; 860 } ; 861 else if (tempcount == 4096) RJMP _0x89 _0x88: LDI R30,LOW(4096) LDI R31,HIGH(4096) CP R30,R6 CPC R31,R7 BRNE _0x8A ; 862 { ; 863 lcd_clear(); CALL SUBOPT_0x4 ; 864 lcd_gotoxy(0,0); ; 865 lcd_putsf("G: Skip"); __POINTW1FN _0,167 ST -Y,R31 ST -Y,R30 CALL _lcd_putsf ; 866 } ; 867 else if (tempcount == 6144) RJMP _0x8B _0x8A: LDI R30,LOW(6144) LDI R31,HIGH(6144) CP R30,R6 CPC R31,R7 BRNE _0x8C ; 868 tempcount = 0; CLR R6 CLR R7 ; 869 ; 870 // first character recieved; show character and move to next state ; 871 if (char_count == 1) _0x8C: _0x8B: _0x89: _0x87: LDS R26,_char_count CPI R26,LOW(0x1) BRNE _0x8D ; 872 { ; 873 lcd_clear(); CALL SUBOPT_0x4 ; 874 lcd_gotoxy(0,0); ; 875 sprintf(lcd_buffer, "%02d: ", thishighscore + 1); LDI R30,LOW(_lcd_buffer) LDI R31,HIGH(_lcd_buffer) ST -Y,R31 ST -Y,R30 __POINTW1FN _0,175 ST -Y,R31 ST -Y,R30 LDS R30,_thishighscore CALL SUBOPT_0x19 LDI R24,4 CALL SUBOPT_0x13 ; 876 lcd_puts(lcd_buffer); ; 877 lcd_gotoxy(4,0); LDI R30,LOW(4) CALL SUBOPT_0x12 ; 878 sprintf(lcd_buffer,"%s",kbd_str); __POINTW1FN _0,182 CALL SUBOPT_0x21 LDI R24,4 CALL SUBOPT_0x13 ; 879 lcd_puts(lcd_buffer); ; 880 ; 881 EnterHighScoreState = 1; LDI R30,LOW(1) MOV R10,R30 ; 882 count = 1; STS _count,R30 ; 883 } ; 884 ; 885 // green button skips high score name entry ; 886 if (greenbuttonPressed) _0x8D: TST R14 BREQ _0x8E ; 887 { ; 888 while (greenbuttonPressed); _0x8F: TST R14 BRNE _0x8F ; 889 HighScoreState = 0; CALL SUBOPT_0x22 ; 890 MainState = HighScoreList; ; 891 tempcount = 0; // used to toggle LCD ; 892 } ; 893 ; 894 break; _0x8E: RJMP _0x84 ; 895 ; 896 case 1: // Drunky is typing their name _0x85: CPI R30,LOW(0x1) BREQ PC+3 JMP _0xA5 ; 897 /* put score number and name, as entered, on LCD; ; 898 backspace deletes char, and enter signals correct name. ; 899 Space and alphanumerics are the ONLY permissible characters ; 900 ; 901 Save name to "thishighscorename" ; 902 */ ; 903 ; 904 // if a new character is received... ; 905 if (char_count != count) LDS R30,_count LDS R26,_char_count CP R30,R26 BREQ _0x93 ; 906 { ; 907 lcd_gotoxy(4,0); LDI R30,LOW(4) CALL SUBOPT_0x12 ; 908 sprintf(lcd_buffer,"%s",kbd_str); __POINTW1FN _0,182 CALL SUBOPT_0x21 LDI R24,4 CALL SUBOPT_0x13 ; 909 lcd_puts(lcd_buffer); ; 910 count = char_count; LDS R30,_char_count STS _count,R30 ; 911 } ; 912 ; 913 // Enter key pressed (and at least one char on screen) ; 914 if (cmd_ready) _0x93: SBRS R2,1 RJMP _0x94 ; 915 { ; 916 UCSRB = 0b10000000; // disable keyboard LDI R30,LOW(128) OUT 0xA,R30 ; 917 ; 918 // name entered into thishighscorename ; 919 for(i=0;kbd_str[i] != 0;i++) LDI R30,0 STS _i,R30 STS _i+1,R30 _0x96: CALL SUBOPT_0x23 CPI R30,0 BREQ _0x97 ; 920 thishighscorename[i]=kbd_str[i]; LDS R30,_i LDS R31,_i+1 SUBI R30,LOW(-_thishighscorename) SBCI R31,HIGH(-_thishighscorename) PUSH R31 PUSH R30 CALL SUBOPT_0x23 POP R26 POP R27 ST X,R30 ; 921 thishighscorename[i]=0; // end in happy C way CALL SUBOPT_0x9 RJMP _0x96 _0x97: LDS R26,_i LDS R27,_i+1 SUBI R26,LOW(-_thishighscorename) SBCI R27,HIGH(-_thishighscorename) LDI R30,LOW(0) ST X,R30 ; 922 ; 923 // if there is at least one character... ; 924 if (i > 0) LDS R26,_i LDS R27,_i+1 CALL __CPW02 BRLT PC+3 JMP _0x98 ; 925 { ; 926 if (numhighscores < 10) LDS R26,_numhighscores CPI R26,LOW(0xA) BRSH _0x99 ; 927 numhighscores++; LDS R30,_numhighscores SUBI R30,-LOW(1) STS _numhighscores,R30 ; 928 ; 929 // shift high scores to make room for new high score ; 930 for (count = min(numhighscores - 1,8); (signed)count >= (signed)thishighscore; count--) _0x99: LDS R30,_numhighscores SUBI R30,LOW(1) LDI R31,0 ST -Y,R31 ST -Y,R30 LDI R30,LOW(8) LDI R31,HIGH(8) ST -Y,R31 ST -Y,R30 CALL _min STS _count,R30 _0x9B: LDS R30,_count LDI R31,0 PUSH R31 PUSH R30 LDS R30,_thishighscore LDI R31,0 POP R26 POP R27 CP R26,R30 CPC R27,R31 BRGE PC+3 JMP _0x9C ; 931 { ; 932 for (count2 = 0; count2 < hsnamelength; count2++) LDI R30,LOW(0) STS _count2,R30 _0x9E: LDS R26,_count2 CPI R26,LOW(0xC) BRSH _0x9F ; 933 { ; 934 highscorenames[count+1][count2] = highscorenames[count][count2]; LDS R30,_count SUBI R30,-LOW(1) LDI R26,LOW(_highscorenames) LDI R27,HIGH(_highscorenames) LDI R31,0 PUSH R27 PUSH R26 LDI R26,LOW(13) LDI R27,HIGH(13) CALL __MULW12U POP R26 POP R27 CALL SUBOPT_0x24 ADD R30,R26 ADC R31,R27 PUSH R31 PUSH R30 LDS R30,_count LDI R26,LOW(_highscorenames) LDI R27,HIGH(_highscorenames) LDI R31,0 PUSH R27 PUSH R26 LDI R26,LOW(13) LDI R27,HIGH(13) CALL __MULW12U POP R26 POP R27 CALL SUBOPT_0x24 ADD R26,R30 ADC R27,R31 LD R30,X POP R26 POP R27 ST X,R30 ; 935 } LDS R30,_count2 SUBI R30,-LOW(1) STS _count2,R30 RJMP _0x9E _0x9F: ; 936 highscores[count+1] = highscores[count]; LDS R30,_count SUBI R30,-LOW(1) CALL SUBOPT_0x25 ADD R30,R26 ADC R31,R27 PUSH R31 PUSH R30 CALL SUBOPT_0x1B POP R26 POP R27 CALL __PUTDP1 ; 937 } LDS R30,_count SUBI R30,LOW(1) STS _count,R30 RJMP _0x9B _0x9C: ; 938 ; 939 // enter this high score ; 940 for (count = 0; count < hsnamelength; count++) LDI R30,LOW(0) STS _count,R30 _0xA1: LDS R26,_count CPI R26,LOW(0xC) BRSH _0xA2 ; 941 { ; 942 highscorenames[thishighscore][count] ; 943 = thishighscorename[count]; LDS R30,_thishighscore LDI R26,LOW(_highscorenames) LDI R27,HIGH(_highscorenames) LDI R31,0 PUSH R27 PUSH R26 LDI R26,LOW(13) LDI R27,HIGH(13) CALL __MULW12U POP R26 POP R27 ADD R26,R30 ADC R27,R31 LDS R30,_count LDI R31,0 ADD R30,R26 ADC R31,R27 PUSH R31 PUSH R30 LDS R30,_count LDI R31,0 SUBI R30,LOW(-_thishighscorename) SBCI R31,HIGH(-_thishighscorename) LD R30,Z POP R26 POP R27 ST X,R30 ; 944 } CALL SUBOPT_0x1E RJMP _0xA1 _0xA2: ; 945 if (BAC < 0.2) LDS R26,_BAC LDS R27,_BAC+1 LDS R24,_BAC+2 LDS R25,_BAC+3 __GETD1N 0x3E4CCCCD CALL __CMPF12 BRSH _0xA3 ; 946 highscores[thishighscore] = BAC; LDS R30,_thishighscore CALL SUBOPT_0x25 ADD R26,R30 ADC R27,R31 LDS R30,_BAC LDS R31,_BAC+1 LDS R22,_BAC+2 LDS R23,_BAC+3 RJMP _0x157 ; 947 else _0xA3: ; 948 highscores[thishighscore] = 0.2; LDS R30,_thishighscore CALL SUBOPT_0x25 ADD R26,R30 ADC R27,R31 __GETD1N 0x3E4CCCCD _0x157: CALL __PUTDP1 ; 949 ; 950 // reset keyboard stuff ; 951 char_count = 0; CALL SUBOPT_0xA ; 952 cmd_ready = 0; BLD R2,1 ; 953 } ; 954 ; 955 // move to High Score List ; 956 HighScoreState = 0; _0x98: CALL SUBOPT_0x22 ; 957 MainState = HighScoreList; ; 958 tempcount = 0; // used to toggle LCD ; 959 } ; 960 break; _0x94: RJMP _0x84 ; 961 default: _0xA5: ; 962 EnterHighScoreState = 0; CLR R10 ; 963 } _0x84: ; 964 } RET ; 965 ; 966 void HighScoreStateMachine(void) ; 967 { _HighScoreStateMachine: ; 968 // INITIAL PRECONDITION: tempcount = 0; HighScoreState = 0; ; 969 ; 970 // if there is at least one high score... ; 971 if (numhighscores > 0) LDS R26,_numhighscores LDI R30,LOW(0) CP R30,R26 BRLO PC+3 JMP _0xA6 ; 972 { ; 973 if (tempcount == 0) MOV R0,R6 OR R0,R7 BRNE _0xA7 ; 974 { ; 975 // print number of high score to lcd_buffer and high score name to lcd_buffer ; 976 sprintf(lcd_buffer, "%0d: %s", HighScoreState + 1,highscorenames[HighScoreState]); LDI R30,LOW(_lcd_buffer) LDI R31,HIGH(_lcd_buffer) ST -Y,R31 ST -Y,R30 __POINTW1FN _0,185 ST -Y,R31 ST -Y,R30 MOV R30,R11 CALL SUBOPT_0x19 MOV R30,R11 LDI R26,LOW(_highscorenames) LDI R27,HIGH(_highscorenames) LDI R31,0 PUSH R27 PUSH R26 LDI R26,LOW(13) LDI R27,HIGH(13) CALL __MULW12U POP R26 POP R27 ADD R30,R26 ADC R31,R27 CLR R22 CLR R23 CALL __PUTPARD1 LDI R24,8 CALL _sprintf ADIW R28,12 ; 977 ; 978 // print name and number to LCD ; 979 lcd_clear(); CALL SUBOPT_0x4 ; 980 lcd_gotoxy(0,0); ; 981 lcd_puts(lcd_buffer); LDI R30,LOW(_lcd_buffer) LDI R31,HIGH(_lcd_buffer) ST -Y,R31 ST -Y,R30 CALL _lcd_puts ; 982 ; 983 // print score to LCD ; 984 lcd_gotoxy(0,1); CALL SUBOPT_0x1A ; 985 sprintf(lcd_buffer, "BAC: %5.3f", highscores[HighScoreState]); LDI R30,LOW(_lcd_buffer) LDI R31,HIGH(_lcd_buffer) ST -Y,R31 ST -Y,R30 __POINTW1FN _0,53 ST -Y,R31 ST -Y,R30 MOV R30,R11 CALL SUBOPT_0x25 CALL SUBOPT_0x18 LDI R24,4 CALL SUBOPT_0x13 ; 986 lcd_puts(lcd_buffer); ; 987 } ; 988 ; 989 // display next high score ; 990 if (numhighscores > HighScoreState + 1 && tempcount == 2048) _0xA7: CALL SUBOPT_0x26 BRSH _0xA9 LDI R30,LOW(2048) LDI R31,HIGH(2048) CP R30,R6 CPC R31,R7 BREQ _0xAA _0xA9: RJMP _0xA8 _0xAA: ; 991 { ; 992 HighScoreState++; INC R11 ; 993 tempcount = 0; CLR R6 CLR R7 ; 994 } ; 995 ; 996 // display command list ; 997 else if (numhighscores == HighScoreState + 1 && tempcount == 2048) RJMP _0xAB _0xA8: CALL SUBOPT_0x26 BRNE _0xAD LDI R30,LOW(2048) LDI R31,HIGH(2048) CP R30,R6 CPC R31,R7 BREQ _0xAE _0xAD: RJMP _0xAC _0xAE: ; 998 { ; 999 lcd_clear(); CALL SUBOPT_0x4 ; 1000 lcd_gotoxy(0,0); ; 1001 lcd_putsf("G: Main Menu"); __POINTW1FN _0,193 CALL SUBOPT_0x5 ; 1002 lcd_gotoxy(0,1); CALL SUBOPT_0x6 ; 1003 lcd_putsf("B: Delete scores"); __POINTW1FN _0,206 ST -Y,R31 ST -Y,R30 CALL _lcd_putsf ; 1004 } ; 1005 else if (tempcount >= 4096) RJMP _0xAF _0xAC: LDI R30,LOW(4096) LDI R31,HIGH(4096) CP R6,R30 CPC R7,R31 BRLO _0xB0 ; 1006 { ; 1007 HighScoreState = 0; CLR R11 ; 1008 tempcount = 0; CLR R6 CLR R7 ; 1009 } ; 1010 } _0xB0: _0xAF: _0xAB: ; 1011 ; 1012 // if there are no high scores... ; 1013 else if (numhighscores == 0) RJMP _0xB1 _0xA6: LDS R30,_numhighscores CPI R30,0 BRNE _0xB2 ; 1014 { ; 1015 if (tempcount == 0) MOV R0,R6 OR R0,R7 BRNE _0xB3 ; 1016 { ; 1017 lcd_clear(); CALL SUBOPT_0x4 ; 1018 lcd_gotoxy(0,0); ; 1019 lcd_putsf("No high scores"); __POINTW1FN _0,223 CALL SUBOPT_0x5 ; 1020 lcd_gotoxy(0,1); CALL SUBOPT_0x6 ; 1021 lcd_putsf("yet!"); __POINTW1FN _0,238 ST -Y,R31 ST -Y,R30 CALL _lcd_putsf ; 1022 } ; 1023 else if (tempcount == 2048) RJMP _0xB4 _0xB3: LDI R30,LOW(2048) LDI R31,HIGH(2048) CP R30,R6 CPC R31,R7 BRNE _0xB5 ; 1024 { ; 1025 lcd_clear(); CALL SUBOPT_0x4 ; 1026 lcd_gotoxy(0,0); ; 1027 lcd_putsf("G: Main Menu"); __POINTW1FN _0,193 CALL SUBOPT_0x5 ; 1028 lcd_gotoxy(0,1); CALL SUBOPT_0x6 ; 1029 lcd_putsf("B: Delete scores"); __POINTW1FN _0,206 ST -Y,R31 ST -Y,R30 CALL _lcd_putsf ; 1030 } ; 1031 else if (tempcount >= 4096) RJMP _0xB6 _0xB5: LDI R30,LOW(4096) LDI R31,HIGH(4096) CP R6,R30 CPC R7,R31 BRLO _0xB7 ; 1032 tempcount = 0; CLR R6 CLR R7 ; 1033 } _0xB7: _0xB6: _0xB4: ; 1034 ; 1035 // to quit the high scores, press green ; 1036 if (greenbuttonPressed) _0xB2: _0xB1: TST R14 BREQ _0xB8 ; 1037 { ; 1038 while (greenbuttonPressed); // wait for release _0xB9: TST R14 BRNE _0xB9 ; 1039 MainState = MainMenu; // back to main menu CALL SUBOPT_0x27 ; 1040 ADC_channel(1); // set ADC to pressure channel ; 1041 ; 1042 // get initial pressure ; 1043 lastpressure = ADC_measure(); ; 1044 thispressure = lastpressure; ; 1045 ; 1046 tempcount = 0; // tempcount is used to toggle LCD ; 1047 } ; 1048 ; 1049 // to delete high scores, press blue ; 1050 else if (bluebuttonPressed) RJMP _0xBC _0xB8: TST R13 BREQ _0xBD ; 1051 { ; 1052 while(bluebuttonPressed); // wait for release _0xBE: TST R13 BRNE _0xBE ; 1053 DeleteHighScores(); CALL _DeleteHighScores ; 1054 tempcount = 0; CLR R6 CLR R7 ; 1055 HighScoreState = 0; CLR R11 ; 1056 } ; 1057 } _0xBD: _0xBC: RET ; 1058 ; 1059 void MainStateMachine(void) ; 1060 { _MainStateMachine: ; 1061 switch(MainState) MOV R30,R8 ; 1062 { ; 1063 // this case is not currently implemented ; 1064 case WarmingUp: CPI R30,0 BREQ PC+3 JMP _0xC4 ; 1065 if (ADC_measure() < tempfloat) CALL _ADC_measure MOVW R26,R30 MOVW R24,R22 LDS R30,_tempfloat LDS R31,_tempfloat+1 LDS R22,_tempfloat+2 LDS R23,_tempfloat+3 CALL __CMPF12 BRSH _0xC5 ; 1066 { ; 1067 tempfloat = ADC_measure(); CALL _ADC_measure STS _tempfloat,R30 STS _tempfloat+1,R31 STS _tempfloat+2,R22 STS _tempfloat+3,R23 ; 1068 lcd_gotoxy(0,1); CALL SUBOPT_0x1A ; 1069 sprintf(lcd_buffer, "%5.3f", tempfloat - 0.7); LDI R30,LOW(_lcd_buffer) LDI R31,HIGH(_lcd_buffer) ST -Y,R31 ST -Y,R30 __POINTW1FN _0,44 ST -Y,R31 ST -Y,R30 LDS R26,_tempfloat LDS R27,_tempfloat+1 LDS R24,_tempfloat+2 LDS R25,_tempfloat+3 __GETD1N 0x3F333333 CALL __SWAPD12 CALL __SUBF12 CALL __PUTPARD1 LDI R24,4 CALL SUBOPT_0x13 ; 1070 lcd_puts(lcd_buffer); ; 1071 } ; 1072 if ((tempfloat < 0.700) || greenbuttonPressed) _0xC5: LDS R26,_tempfloat LDS R27,_tempfloat+1 LDS R24,_tempfloat+2 LDS R25,_tempfloat+3 __GETD1N 0x3F333333 CALL __CMPF12 BRLO _0xC7 TST R14 BREQ _0xC6 _0xC7: ; 1073 // ETOH voltage has settled down after initial spike ; 1074 { ; 1075 while (greenbuttonPressed); // wait for release _0xC9: TST R14 BRNE _0xC9 ; 1076 MainState = MainMenu; // move to "Main Menu" state CALL SUBOPT_0x27 ; 1077 ADC_channel(1); // set ADC to pressure channel ; 1078 ; 1079 // get initial pressure ; 1080 lastpressure = ADC_measure(); ; 1081 thispressure = lastpressure; ; 1082 ; 1083 tempcount = 0; // tempcount is used to toggle LCD ; 1084 } ; 1085 ; 1086 break; _0xC6: RJMP _0xC3 ; 1087 ; 1088 case MainMenu: _0xC4: CPI R30,LOW(0x1) BREQ PC+3 JMP _0xCC ; 1089 // INITIAL PRECONDITION: tempcount = 0; ADC_channel(1); ; 1090 // initial pressure measured; ; 1091 ; 1092 // measure pressure ; 1093 if ((tempcount & 511) == 0) CALL SUBOPT_0x16 BRNE _0xCD ; 1094 { ; 1095 lastpressure = thispressure; LDS R30,_thispressure LDS R31,_thispressure+1 LDS R22,_thispressure+2 LDS R23,_thispressure+3 STS _lastpressure,R30 STS _lastpressure+1,R31 STS _lastpressure+2,R22 STS _lastpressure+3,R23 ; 1096 thispressure = ADC_measure(); CALL _ADC_measure STS _thispressure,R30 STS _thispressure+1,R31 STS _thispressure+2,R22 STS _thispressure+3,R23 ; 1097 } ; 1098 ; 1099 if (tempcount == 0) _0xCD: MOV R0,R6 OR R0,R7 BRNE _0xCE ; 1100 { ; 1101 lcd_clear(); CALL SUBOPT_0x4 ; 1102 lcd_gotoxy(0,0); ; 1103 lcd_putsf("Main Menu"); __POINTW1FN _0,196 ST -Y,R31 ST -Y,R30 CALL _lcd_putsf ; 1104 } ; 1105 else if (tempcount == 1024) RJMP _0xCF _0xCE: LDI R30,LOW(1024) LDI R31,HIGH(1024) CP R30,R6 CPC R31,R7 BRNE _0xD0 ; 1106 { ; 1107 lcd_clear(); CALL SUBOPT_0x4 ; 1108 lcd_gotoxy(0,0); ; 1109 lcd_putsf("G: High Scores"); __POINTW1FN _0,243 CALL SUBOPT_0x5 ; 1110 lcd_gotoxy(0,1); CALL SUBOPT_0x6 ; 1111 lcd_putsf("B: Force Sample"); __POINTW1FN _0,258 CALL SUBOPT_0x5 ; 1112 ; 1113 ADC_channel(0); CALL _ADC_channel ; 1114 tempfloat = ADC_measure(); // get ETOH voltage sample CALL _ADC_measure STS _tempfloat,R30 STS _tempfloat+1,R31 STS _tempfloat+2,R22 STS _tempfloat+3,R23 ; 1115 ADC_channel(1); LDI R30,LOW(1) ST -Y,R30 CALL _ADC_channel ; 1116 } ; 1117 else if ((tempcount == 2048) && (tempfloat <= 0.32)) RJMP _0xD1 _0xD0: LDI R30,LOW(2048) LDI R31,HIGH(2048) CP R30,R6 CPC R31,R7 BRNE _0xD3 LDS R26,_tempfloat LDS R27,_tempfloat+1 LDS R24,_tempfloat+2 LDS R25,_tempfloat+3 __GETD1N 0x3EA3D70A CALL __CMPF12 BREQ PC+4 BRCS PC+3 JMP _0xD3 RJMP _0xD4 _0xD3: RJMP _0xD2 _0xD4: ; 1118 { ; 1119 lcd_clear(); CALL SUBOPT_0x4 ; 1120 lcd_gotoxy(0,0); ; 1121 lcd_putsf("Or just start"); __POINTW1FN _0,274 CALL SUBOPT_0x5 ; 1122 lcd_gotoxy(0,1); CALL SUBOPT_0x6 ; 1123 lcd_putsf("blowing!"); __POINTW1FN _0,288 ST -Y,R31 ST -Y,R30 CALL _lcd_putsf ; 1124 } ; 1125 else if ((tempcount == 2048)) RJMP _0xD5 _0xD2: LDI R30,LOW(2048) LDI R31,HIGH(2048) CP R30,R6 CPC R31,R7 BRNE _0xD6 ; 1126 { ; 1127 lcd_clear(); CALL SUBOPT_0x4 ; 1128 lcd_gotoxy(0,0); ; 1129 lcd_putsf("Warning"); __POINTW1FN _0,297 CALL SUBOPT_0x5 ; 1130 lcd_gotoxy(0,1); CALL SUBOPT_0x6 ; 1131 sprintf(lcd_buffer, "%4.2f > 0.31", tempfloat); LDI R30,LOW(_lcd_buffer) LDI R31,HIGH(_lcd_buffer) ST -Y,R31 ST -Y,R30 __POINTW1FN _0,305 ST -Y,R31 ST -Y,R30 LDS R30,_tempfloat LDS R31,_tempfloat+1 LDS R22,_tempfloat+2 LDS R23,_tempfloat+3 CALL __PUTPARD1 LDI R24,4 CALL SUBOPT_0x13 ; 1132 lcd_puts(lcd_buffer); ; 1133 } ; 1134 else if (tempcount >= 3072) RJMP _0xD7 _0xD6: LDI R30,LOW(3072) LDI R31,HIGH(3072) CP R6,R30 CPC R7,R31 BRLO _0xD8 ; 1135 { ; 1136 tempcount = 0; CLR R6 CLR R7 ; 1137 } ; 1138 ; 1139 if (greenbuttonPressed) _0xD8: _0xD7: _0xD5: _0xD1: _0xCF: TST R14 BREQ _0xD9 ; 1140 { ; 1141 // wait for button release ; 1142 while(greenbuttonPressed); _0xDA: TST R14 BRNE _0xDA ; 1143 ; 1144 MainState = HighScoreList; // move to high score list CALL SUBOPT_0x20 ; 1145 HighScoreState = 0; ; 1146 tempcount = 0; // used to toggle LCD ; 1147 } ; 1148 ; 1149 ; 1150 // if the pressure has changed on our broken sensor... ; 1151 // or if the blue button is pressed... ; 1152 // someone is breathing into the Breath-o-Matic ; 1153 else if (thispressure > lastpressure + bpg || bluebuttonPressed) RJMP _0xDD _0xD9: LDS R30,_lastpressure LDS R31,_lastpressure+1 LDS R22,_lastpressure+2 LDS R23,_lastpressure+3 __GETD2N 0x3E99999A CALL __ADDF12 LDS R26,_thispressure LDS R27,_thispressure+1 LDS R24,_thispressure+2 LDS R25,_thispressure+3 CALL __CMPF12 BREQ PC+4 BRCS PC+3 JMP _0xDF TST R13 BREQ _0xDE _0xDF: ; 1154 { ; 1155 while(bluebuttonPressed); // wait for release _0xE1: TST R13 BRNE _0xE1 ; 1156 MainState = TakingSample; LDI R30,LOW(2) MOV R8,R30 ; 1157 TestBreathState = 0; CLR R9 ; 1158 lcd_clear(); CALL SUBOPT_0x4 ; 1159 lcd_gotoxy(0,0); ; 1160 lcd_putsf("Breathe, Monkey!"); __POINTW1FN _0,318 ST -Y,R31 ST -Y,R30 CALL _lcd_putsf ; 1161 tempcount = 0; // used to time breath samples CALL SUBOPT_0x11 ; 1162 count = 0; // used for sample number ; 1163 } ; 1164 break; _0xDE: _0xDD: RJMP _0xC3 ; 1165 ; 1166 case TakingSample: _0xCC: CPI R30,LOW(0x2) BRNE _0xE4 ; 1167 TestBreathStateMachine(); CALL _TestBreathStateMachine ; 1168 break; RJMP _0xC3 ; 1169 ; 1170 case EnteringHighScore: _0xE4: CPI R30,LOW(0x3) BRNE _0xE5 ; 1171 EnterHighScoreStateMachine(); CALL _EnterHighScoreStateMachine ; 1172 break; RJMP _0xC3 ; 1173 ; 1174 case HighScoreList: _0xE5: CPI R30,LOW(0x4) BRNE _0xE7 ; 1175 HighScoreStateMachine(); CALL _HighScoreStateMachine ; 1176 break; RJMP _0xC3 ; 1177 ; 1178 default: _0xE7: ; 1179 MainState = MainMenu; LDI R30,LOW(1) MOV R8,R30 ; 1180 } _0xC3: ; 1181 } RET _getchar: sbis usr,rxc rjmp _getchar in r30,udr RET _putchar: sbis usr,udre rjmp _putchar ld r30,y out udr,r30 ADIW R28,1 RET __put_G2: put: LD R26,Y LDD R27,Y+1 CALL __GETW1P SBIW R30,0 BREQ _0xE8 CALL __GETW1P ADIW R30,1 ST X+,R30 ST X,R31 SBIW R30,1 LDD R26,Y+2 STD Z+0,R26 RJMP _0xE9 _0xE8: LDD R30,Y+2 ST -Y,R30 CALL _putchar _0xE9: ADIW R28,3 RET __print_G2: SBIW R28,6 CALL __SAVELOCR6 LDI R16,0 _0xEA: LDD R30,Y+16 LDD R31,Y+16+1 ADIW R30,1 STD Y+16,R30 STD Y+16+1,R31 SBIW R30,1 LPM R30,Z MOV R19,R30 CPI R30,0 BRNE PC+3 JMP _0xEC MOV R30,R16 CPI R30,0 BRNE _0xF0 CPI R19,37 BRNE _0xF1 LDI R16,LOW(1) RJMP _0xF2 _0xF1: CALL SUBOPT_0x28 _0xF2: RJMP _0xEF _0xF0: CPI R30,LOW(0x1) BRNE _0xF3 CPI R19,37 BRNE _0xF4 CALL SUBOPT_0x28 LDI R16,LOW(0) RJMP _0xEF _0xF4: LDI R16,LOW(2) LDI R21,LOW(0) LDI R17,LOW(0) CPI R19,45 BRNE _0xF5 LDI R17,LOW(1) RJMP _0xEF _0xF5: CPI R19,43 BRNE _0xF6 LDI R21,LOW(43) RJMP _0xEF _0xF6: CPI R19,32 BRNE _0xF7 LDI R21,LOW(32) RJMP _0xEF _0xF7: RJMP _0xF8 _0xF3: CPI R30,LOW(0x2) BRNE _0xF9 _0xF8: LDI R20,LOW(0) LDI R16,LOW(3) CPI R19,48 BRNE _0xFA ORI R17,LOW(128) RJMP _0xEF _0xFA: RJMP _0xFB _0xF9: CPI R30,LOW(0x3) BREQ PC+3 JMP _0xEF _0xFB: CPI R19,48 BRLO _0xFE CPI R19,58 BRLO _0xFF _0xFE: RJMP _0xFD _0xFF: MOV R26,R20 LDI R30,LOW(10) MUL R30,R26 MOV R30,R0 MOV R20,R30 MOV R30,R19 SUBI R30,LOW(48) ADD R20,R30 RJMP _0xEF _0xFD: MOV R30,R19 CPI R30,LOW(0x63) BRNE _0x103 CALL SUBOPT_0x29 LD R30,X CALL SUBOPT_0x2A RJMP _0x104 _0x103: CPI R30,LOW(0x73) BRNE _0x106 CALL SUBOPT_0x29 CALL SUBOPT_0x2B CALL _strlen MOV R16,R30 RJMP _0x107 _0x106: CPI R30,LOW(0x70) BRNE _0x109 CALL SUBOPT_0x29 CALL SUBOPT_0x2B CALL _strlenf MOV R16,R30 ORI R17,LOW(8) _0x107: ORI R17,LOW(2) ANDI R17,LOW(127) LDI R18,LOW(0) RJMP _0x10A _0x109: CPI R30,LOW(0x64) BREQ _0x10D CPI R30,LOW(0x69) BRNE _0x10E _0x10D: ORI R17,LOW(4) RJMP _0x10F _0x10E: CPI R30,LOW(0x75) BRNE _0x110 _0x10F: LDI R30,LOW(_tbl10_G2*2) LDI R31,HIGH(_tbl10_G2*2) STD Y+6,R30 STD Y+6+1,R31 LDI R16,LOW(5) RJMP _0x111 _0x110: CPI R30,LOW(0x58) BRNE _0x113 ORI R17,LOW(8) RJMP _0x114 _0x113: CPI R30,LOW(0x78) BREQ PC+3 JMP _0x142 _0x114: LDI R30,LOW(_tbl16_G2*2) LDI R31,HIGH(_tbl16_G2*2) STD Y+6,R30 STD Y+6+1,R31 LDI R16,LOW(4) _0x111: SBRS R17,2 RJMP _0x116 CALL SUBOPT_0x29 CALL __GETW1P STD Y+10,R30 STD Y+10+1,R31 LDD R26,Y+10 LDD R27,Y+10+1 SBIW R26,0 BRGE _0x117 CALL __ANEGW1 STD Y+10,R30 STD Y+10+1,R31 LDI R21,LOW(45) _0x117: CPI R21,0 BREQ _0x118 SUBI R16,-LOW(1) RJMP _0x119 _0x118: ANDI R17,LOW(251) _0x119: RJMP _0x11A _0x116: CALL SUBOPT_0x29 CALL __GETW1P STD Y+10,R30 STD Y+10+1,R31 _0x11A: _0x10A: SBRC R17,0 RJMP _0x11B _0x11C: CP R16,R20 BRSH _0x11E SBRS R17,7 RJMP _0x11F SBRS R17,2 RJMP _0x120 ANDI R17,LOW(251) MOV R19,R21 SUBI R16,LOW(1) RJMP _0x121 _0x120: LDI R19,LOW(48) _0x121: RJMP _0x122 _0x11F: LDI R19,LOW(32) _0x122: CALL SUBOPT_0x28 SUBI R20,LOW(1) RJMP _0x11C _0x11E: _0x11B: MOV R18,R16 SBRS R17,1 RJMP _0x123 _0x124: CPI R18,0 BREQ _0x126 SBRS R17,3 RJMP _0x127 LDD R30,Y+6 LDD R31,Y+6+1 ADIW R30,1 STD Y+6,R30 STD Y+6+1,R31 SBIW R30,1 LPM R30,Z RJMP _0x158 _0x127: LDD R26,Y+6 LDD R27,Y+6+1 LD R30,X+ STD Y+6,R26 STD Y+6+1,R27 _0x158: ST -Y,R30 CALL SUBOPT_0x2C CPI R20,0 BREQ _0x129 SUBI R20,LOW(1) _0x129: SUBI R18,LOW(1) RJMP _0x124 _0x126: RJMP _0x12A _0x123: _0x12C: LDI R19,LOW(48) LDD R30,Y+6 LDD R31,Y+6+1 ADIW R30,2 STD Y+6,R30 STD Y+6+1,R31 SBIW R30,2 CALL __GETW1PF STD Y+8,R30 STD Y+8+1,R31 ldd r26,y+10 ;R26,R27=n ldd r27,y+11 calc_digit: cp r26,r30 cpc r27,r31 brlo calc_digit_done SUBI R19,-LOW(1) sub r26,r30 sbc r27,r31 brne calc_digit calc_digit_done: std Y+10,r26 ;n=R26,R27 std y+11,r27 LDI R30,LOW(57) CP R30,R19 BRSH _0x12E SBRS R17,3 RJMP _0x12F SUBI R19,-LOW(7) RJMP _0x130 _0x12F: SUBI R19,-LOW(39) _0x130: _0x12E: SBRC R17,4 RJMP _0x132 LDI R30,LOW(48) CP R30,R19 BRLO _0x134 LDD R26,Y+8 LDD R27,Y+8+1 CPI R26,LOW(0x1) LDI R30,HIGH(0x1) CPC R27,R30 BRNE _0x133 _0x134: ORI R17,LOW(16) RJMP _0x136 _0x133: CP R20,R18 BRLO _0x138 SBRS R17,0 RJMP _0x139 _0x138: RJMP _0x137 _0x139: LDI R19,LOW(32) SBRS R17,7 RJMP _0x13A LDI R19,LOW(48) ORI R17,LOW(16) _0x136: SBRS R17,2 RJMP _0x13B ANDI R17,LOW(251) ST -Y,R21 CALL SUBOPT_0x2C CPI R20,0 BREQ _0x13C SUBI R20,LOW(1) _0x13C: _0x13B: _0x13A: _0x132: CALL SUBOPT_0x28 CPI R20,0 BREQ _0x13D SUBI R20,LOW(1) _0x13D: _0x137: SUBI R18,LOW(1) LDD R26,Y+8 LDD R27,Y+8+1 LDI R30,LOW(1) LDI R31,HIGH(1) CP R30,R26 CPC R31,R27 BRSH _0x12D RJMP _0x12C _0x12D: _0x12A: SBRS R17,0 RJMP _0x13E _0x13F: CPI R20,0 BREQ _0x141 SUBI R20,LOW(1) LDI R30,LOW(32) CALL SUBOPT_0x2A RJMP _0x13F _0x141: _0x13E: _0x142: _0x104: LDI R16,LOW(0) _0xEF: RJMP _0xEA _0xEC: CALL __LOADLOCR6 ADIW R28,18 RET _sprintf: PUSH R15 MOV R15,R24 SBIW R28,2 ST -Y,R17 ST -Y,R16 MOVW R26,R28 CALL __ADDW2R15 __PUTW2R 16,17 MOVW R26,R28 ADIW R26,6 CALL __ADDW2R15 CALL __GETW1P STD Y+2,R30 STD Y+2+1,R31 MOVW R26,R28 ADIW R26,4 CALL __ADDW2R15 CALL __GETW1P ST -Y,R31 ST -Y,R30 ST -Y,R17 ST -Y,R16 MOVW R30,R28 ADIW R30,6 ST -Y,R31 ST -Y,R30 CALL __print_G2 LDD R26,Y+2 LDD R27,Y+2+1 LDI R30,LOW(0) ST X,R30 LDD R17,Y+1 LDD R16,Y+0 ADIW R28,4 POP R15 RET _min: ld r26,y+ ld r27,y+ ld r30,y+ ld r31,y+ cp r30,r26 cpc r31,r27 brlt __min0 movw r30,r26 __min0: ret _log: SBIW R28,4 ST -Y,R17 ST -Y,R16 __GETD2S 6 CALL __CPD02 BRLT _0x143 __GETD1N 0xFF7FFFFF RJMP _0x153 _0x143: __GETD1S 6 CALL __PUTPARD1 IN R30,SPL IN R31,SPH SBIW R30,1 ST -Y,R31 ST -Y,R30 PUSH R17 PUSH R16 CALL _frexp POP R16 POP R17 __PUTD1S 6 __GETD2S 6 __GETD1N 0x3F3504F3 CALL __CMPF12 BRSH _0x144 __GETD1S 6 CALL __ADDF12 __PUTD1S 6 __SUBWRN 16,17,1 _0x144: __GETD2S 6 CALL SUBOPT_0x8 PUSH R23 PUSH R22 PUSH R31 PUSH R30 __GETD1S 6 __GETD2N 0x3F800000 CALL __ADDF12 POP R26 POP R27 POP R24 POP R25 CALL __DIVF21 CALL SUBOPT_0x2D __GETD2N 0x3F654226 CALL __MULF12 MOVW R26,R30 MOVW R24,R22 __GETD1N 0x4054114E CALL __SWAPD12 CALL __SUBF12 __GETD2S 6 CALL __MULF12 PUSH R23 PUSH R22 PUSH R31 PUSH R30 __GETD2S 2 __GETD1N 0x3FD4114D CALL __SWAPD12 CALL __SUBF12 POP R26 POP R27 POP R24 POP R25 CALL __DIVF21 PUSH R23 PUSH R22 PUSH R31 PUSH R30 __GETW1R 16,17 __GETD2N 0x3F317218 CALL __CWD1 CALL __CDF1 CALL __MULF12 POP R26 POP R27 POP R24 POP R25 CALL __ADDF12 _0x153: LDD R17,Y+1 LDD R16,Y+0 ADIW R28,10 RET _exp: SBIW R28,8 ST -Y,R17 ST -Y,R16 __GETD2S 10 __GETD1N 0xC2AEAC50 CALL __CMPF12 BRSH _0x145 __GETD1N 0x0 RJMP _0x152 _0x145: __GETD1S 10 CALL __CPD10 BRNE _0x146 __GETD1N 0x3F800000 RJMP _0x152 _0x146: __GETD2S 10 __GETD1N 0x42B17218 CALL __CMPF12 BREQ PC+2 BRCC PC+3 JMP _0x147 __GETD1N 0x7F7FFFFF RJMP _0x152 _0x147: __GETD2S 10 __GETD1N 0x3FB8AA3B CALL __MULF12 __PUTD1S 10 CALL __PUTPARD1 CALL _floor CALL __CFD1 __PUTW1R 16,17 __GETW1R 16,17 __GETD2S 10 CALL __CWD1 CALL __CDF1 CALL __SWAPD12 CALL __SUBF12 MOVW R26,R30 MOVW R24,R22 __GETD1N 0x3F000000 CALL __SWAPD12 CALL __SUBF12 CALL SUBOPT_0x2D __GETD2N 0x3D6C4C6D CALL __MULF12 __GETD2N 0x40E6E3A6 CALL __ADDF12 __GETD2S 6 CALL __MULF12 __PUTD1S 6 __GETD1S 2 __GETD2N 0x41A68D28 CALL __ADDF12 __PUTD1S 2 __GETD1S 6 __GETD2S 2 CALL __ADDF12 __GETD2N 0x3FB504F3 CALL __MULF12 PUSH R23 PUSH R22 PUSH R31 PUSH R30 __GETD2S 6 __GETD1S 2 CALL __SUBF12 POP R26 POP R27 POP R24 POP R25 CALL __DIVF21 CALL __PUTPARD1 ST -Y,R17 ST -Y,R16 CALL _ldexp _0x152: LDD R17,Y+1 LDD R16,Y+0 ADIW R28,14 RET _pow: SBIW R28,4 __GETD1S 8 CALL __CPD10 BRNE _0x148 __GETD1N 0x0 RJMP _0x151 _0x148: __GETD2S 8 CALL __CPD02 BRGE _0x149 __GETD1S 4 CALL __CPD10 BRNE _0x14A __GETD1N 0x3F800000 RJMP _0x151 _0x14A: __GETD1S 8 CALL SUBOPT_0x2E RJMP _0x151 _0x149: __GETD1S 4 MOVW R26,R28 CALL __CFD1 CALL __PUTDP1 __GETD1S 0 CALL __CDF1 MOVW R26,R30 MOVW R24,R22 __GETD1S 4 CALL __CPD12 BREQ _0x14B __GETD1N 0x0 RJMP _0x151 _0x14B: __GETD1S 8 CALL __ANEGF1 CALL SUBOPT_0x2E __PUTD1S 8 LD R30,Y ANDI R30,LOW(0x1) BRNE _0x14C __GETD1S 8 RJMP _0x151 _0x14C: __GETD1S 8 CALL __ANEGF1 _0x151: ADIW R28,12 RET .equ __lcd_direction=__lcd_port-1 .equ __lcd_pin=__lcd_port-2 .equ __lcd_rs=0 .equ __lcd_rd=1 .equ __lcd_enable=2 .equ __lcd_busy_flag=7 .DSEG __base_y_G5: .BYTE 0x4 __lcd_x: .BYTE 0x1 __lcd_y: .BYTE 0x1 __lcd_maxx: .BYTE 0x1 .CSEG __lcd_ready: in r26,__lcd_direction andi r26,0xf ;set as input out __lcd_direction,r26 sbi __lcd_port,__lcd_rd ;RD=1 cbi __lcd_port,__lcd_rs ;RS=0 __lcd_busy: rcall __lcd_delay sbi __lcd_port,__lcd_enable ;EN=1 rcall __lcd_delay in r26,__lcd_pin cbi __lcd_port,__lcd_enable ;EN=0 rcall __lcd_delay sbi __lcd_port,__lcd_enable ;EN=1 rcall __lcd_delay cbi __lcd_port,__lcd_enable ;EN=0 sbrc r26,__lcd_busy_flag rjmp __lcd_busy RET __lcd_write_nibble: andi r26,0xf0 or r26,r27 out __lcd_port,r26 ;write sbi __lcd_port,__lcd_enable ;EN=1 rcall __lcd_delay cbi __lcd_port,__lcd_enable ;EN=0 __lcd_delay: ldi r31,15 __lcd_delay0: dec r31 brne __lcd_delay0 ret __lcd_write_data: cbi __lcd_port,__lcd_rd ;RD=0 in r26,__lcd_direction ori r26,0xf0 | (1<<__lcd_rs) | (1<<__lcd_rd) | (1<<__lcd_enable) ;set as output out __lcd_direction,r26 in r27,__lcd_port andi r27,0xf ld r26,y rcall __lcd_write_nibble ;RD=0, write MSN ld r26,y swap r26 rcall __lcd_write_nibble ;write LSN sbi __lcd_port,__lcd_rd ;RD=1 ADIW R28,1 RET __lcd_read_nibble: sbi __lcd_port,__lcd_enable ;EN=1 rcall __lcd_delay in r30,__lcd_pin ;read cbi __lcd_port,__lcd_enable ;EN=0 rcall __lcd_delay andi r30,0xf0 ret _lcd_read_byte0_G5: rcall __lcd_delay rcall __lcd_read_nibble ;read MSN mov r26,r30 rcall __lcd_read_nibble ;read LSN cbi __lcd_port,__lcd_rd ;RD=0 swap r30 or r30,r26 RET _lcd_gotoxy: CALL __lcd_ready LD R30,Y LDI R31,0 SUBI R30,LOW(-__base_y_G5) SBCI R31,HIGH(-__base_y_G5) LD R30,Z LDD R26,Y+1 ADD R30,R26 ST -Y,R30 CALL __lcd_write_data LDD R30,Y+1 STS __lcd_x,R30 LD R30,Y STS __lcd_y,R30 ADIW R28,2 RET _lcd_clear: CALL __lcd_ready LDI R30,LOW(2) CALL SUBOPT_0x2F LDI R30,LOW(12) CALL SUBOPT_0x2F LDI R30,LOW(1) ST -Y,R30 CALL __lcd_write_data LDI R30,LOW(0) STS __lcd_y,R30 STS __lcd_x,R30 RET _lcd_putchar: push r30 push r31 ld r26,y set cpi r26,10 breq __lcd_putchar1 clt LDS R30,__lcd_x SUBI R30,-LOW(1) STS __lcd_x,R30 LDS R30,__lcd_maxx LDS R26,__lcd_x CP R30,R26 BRSH _0x14E __lcd_putchar1: LDS R30,__lcd_y SUBI R30,-LOW(1) STS __lcd_y,R30 LDI R30,LOW(0) ST -Y,R30 LDS R30,__lcd_y ST -Y,R30 CALL _lcd_gotoxy brts __lcd_putchar0 _0x14E: rcall __lcd_ready sbi __lcd_port,__lcd_rs ;RS=1 ld r26,y st -y,r26 rcall __lcd_write_data __lcd_putchar0: pop r31 pop r30 ADIW R28,1 RET _lcd_puts: ldd r31,y+1 ld r30,y __lcd_puts0: ld r26,z+ tst r26 breq __lcd_puts1 st -y,r26 rcall _lcd_putchar rjmp __lcd_puts0 __lcd_puts1: ADIW R28,2 RET _lcd_putsf: ld r30,y ldd r31,y+1 __lcd_putsf0: lpm tst r0 breq __lcd_putsf1 adiw r30,1 st -y,r0 rcall _lcd_putchar rjmp __lcd_putsf0 __lcd_putsf1: ADIW R28,2 RET __long_delay_G5: clr r26 clr r27 __long_delay0: sbiw r26,1 ;2 cycles brne __long_delay0 ;2 cycles RET __lcd_init_write_G5: cbi __lcd_port,__lcd_rd ;RD=0 in r26,__lcd_direction ori r26,0xf7 ;set as output out __lcd_direction,r26 in r27,__lcd_port andi r27,0xf ld r26,y rcall __lcd_write_nibble ;RD=0, write MSN sbi __lcd_port,__lcd_rd ;RD=1 ADIW R28,1 RET _lcd_init: cbi __lcd_port,__lcd_enable ;EN=0 cbi __lcd_port,__lcd_rs ;RS=0 LD R30,Y STS __lcd_maxx,R30 SUBI R30,-LOW(128) __PUTB1MN __base_y_G5,2 LD R30,Y SUBI R30,-LOW(192) __PUTB1MN __base_y_G5,3 CALL SUBOPT_0x30 CALL SUBOPT_0x30 CALL SUBOPT_0x30 CALL __long_delay_G5 LDI R30,LOW(32) ST -Y,R30 CALL __lcd_init_write_G5 CALL __long_delay_G5 LDI R30,LOW(40) CALL SUBOPT_0x31 LDI R30,LOW(4) CALL SUBOPT_0x31 LDI R30,LOW(133) CALL SUBOPT_0x31 in r26,__lcd_direction andi r26,0xf ;set as input out __lcd_direction,r26 sbi __lcd_port,__lcd_rd ;RD=1 CALL _lcd_read_byte0_G5 CPI R30,LOW(0x5) BREQ _0x14F LDI R30,LOW(0) RJMP _0x150 _0x14F: CALL __lcd_ready LDI R30,LOW(6) ST -Y,R30 CALL __lcd_write_data CALL _lcd_clear LDI R30,LOW(1) _0x150: ADIW R28,1 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x0: ST -Y,R0 ST -Y,R1 ST -Y,R15 ST -Y,R22 ST -Y,R23 ST -Y,R24 ST -Y,R25 ST -Y,R26 ST -Y,R27 ST -Y,R30 ST -Y,R31 IN R30,SREG ST -Y,R30 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x1: LD R30,Y+ OUT SREG,R30 LD R31,Y+ LD R30,Y+ LD R27,Y+ LD R26,Y+ LD R25,Y+ LD R24,Y+ LD R23,Y+ LD R22,Y+ LD R15,Y+ LD R1,Y+ LD R0,Y+ RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x2: LDS R26,_char_count LDI R27,0 SUBI R26,LOW(-_kbd_str) SBCI R27,HIGH(-_kbd_str) LDI R30,LOW(0) ST X,R30 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 3 TIMES SUBOPT_0x3: LDI R30,LOW(1) ST -Y,R30 CALL _ADC_channel CALL _ADC_measure STS _lastpressure,R30 STS _lastpressure+1,R31 STS _lastpressure+2,R22 STS _lastpressure+3,R23 STS _thispressure,R30 STS _thispressure+1,R31 STS _thispressure+2,R22 STS _thispressure+3,R23 CLR R6 CLR R7 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 18 TIMES SUBOPT_0x4: CALL _lcd_clear LDI R30,LOW(0) ST -Y,R30 ST -Y,R30 JMP _lcd_gotoxy ;OPTIMIZER ADDED SUBROUTINE, CALLED 12 TIMES SUBOPT_0x5: ST -Y,R31 ST -Y,R30 CALL _lcd_putsf LDI R30,LOW(0) ST -Y,R30 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 16 TIMES SUBOPT_0x6: LDI R30,LOW(1) ST -Y,R30 JMP _lcd_gotoxy ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x7: ST -Y,R31 ST -Y,R30 CALL _lcd_putsf LDI R30,LOW(2000) LDI R31,HIGH(2000) ST -Y,R31 ST -Y,R30 JMP _delay_ms ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x8: __GETD1N 0x3F800000 CALL __SWAPD12 CALL __SUBF12 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x9: LDS R30,_i LDS R31,_i+1 ADIW R30,1 STS _i,R30 STS _i+1,R31 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0xA: LDI R30,LOW(0) STS _char_count,R30 CLT RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 13 TIMES SUBOPT_0xB: IN R30,0x25 ANDI R30,0xEF OUT 0x25,R30 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 14 TIMES SUBOPT_0xC: IN R30,0x25 ORI R30,0x10 OUT 0x25,R30 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 19 TIMES SUBOPT_0xD: LDI R30,LOW(100) LDI R31,HIGH(100) ST -Y,R31 ST -Y,R30 JMP _delay_ms ;OPTIMIZER ADDED SUBROUTINE, CALLED 3 TIMES SUBOPT_0xE: ST -Y,R31 ST -Y,R30 CALL _delay_ms RJMP SUBOPT_0xB ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0xF: LDI R30,LOW(200) LDI R31,HIGH(200) ST -Y,R31 ST -Y,R30 JMP _delay_ms ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x10: IN R30,0x23 SUBI R30,LOW(5) OUT 0x23,R30 RJMP SUBOPT_0xC ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x11: CLR R6 CLR R7 LDI R30,LOW(0) STS _count,R30 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 3 TIMES SUBOPT_0x12: ST -Y,R30 LDI R30,LOW(0) ST -Y,R30 CALL _lcd_gotoxy LDI R30,LOW(_lcd_buffer) LDI R31,HIGH(_lcd_buffer) ST -Y,R31 ST -Y,R30 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 11 TIMES SUBOPT_0x13: CALL _sprintf ADIW R28,8 LDI R30,LOW(_lcd_buffer) LDI R31,HIGH(_lcd_buffer) ST -Y,R31 ST -Y,R30 JMP _lcd_puts ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x14: LDI R30,LOW(0) ST -Y,R30 CALL _Speaker LDS R30,_count SUBI R30,-LOW(1) STS _count,R30 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x15: LDI R30,LOW(1000) LDI R31,HIGH(1000) ST -Y,R31 ST -Y,R30 JMP _delay_ms ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x16: __GETW1R 6,7 ANDI R31,HIGH(0x1FF) SBIW R30,0 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x17: LDS R30,_count LDI R26,LOW(_BAC_samples) LDI R27,HIGH(_BAC_samples) LDI R31,0 LSL R30 ROL R31 LSL R30 ROL R31 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x18: ADD R26,R30 ADC R27,R31 CALL __GETD1P CALL __PUTPARD1 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 3 TIMES SUBOPT_0x19: SUBI R30,-LOW(1) CLR R31 CLR R22 CLR R23 CALL __PUTPARD1 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 3 TIMES SUBOPT_0x1A: LDI R30,LOW(0) ST -Y,R30 RJMP SUBOPT_0x6 ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x1B: LDS R30,_count LDI R26,LOW(_highscores) LDI R27,HIGH(_highscores) LDI R31,0 LSL R30 ROL R31 LSL R30 ROL R31 ADD R26,R30 ADC R27,R31 CALL __GETD1P RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x1C: LDI R30,LOW(3) MOV R8,R30 CLR R10 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x1D: STS _thishighscore,R30 LDI R30,LOW(144) OUT 0xA,R30 CLR R6 CLR R7 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x1E: LDS R30,_count SUBI R30,-LOW(1) STS _count,R30 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x1F: LDS R30,_numhighscores LDS R26,_count CP R30,R26 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x20: LDI R30,LOW(4) MOV R8,R30 CLR R11 CLR R6 CLR R7 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x21: ST -Y,R31 ST -Y,R30 LDI R30,LOW(_kbd_str) LDI R31,HIGH(_kbd_str) CLR R22 CLR R23 CALL __PUTPARD1 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x22: CLR R11 LDI R30,LOW(4) MOV R8,R30 CLR R6 CLR R7 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x23: LDS R30,_i LDS R31,_i+1 SUBI R30,LOW(-_kbd_str) SBCI R31,HIGH(-_kbd_str) LD R30,Z RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x24: ADD R26,R30 ADC R27,R31 LDS R30,_count2 LDI R31,0 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 4 TIMES SUBOPT_0x25: LDI R26,LOW(_highscores) LDI R27,HIGH(_highscores) LDI R31,0 LSL R30 ROL R31 LSL R30 ROL R31 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x26: MOV R30,R11 SUBI R30,-LOW(1) LDS R26,_numhighscores CP R30,R26 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x27: LDI R30,LOW(1) MOV R8,R30 RJMP SUBOPT_0x3 ;OPTIMIZER ADDED SUBROUTINE, CALLED 4 TIMES SUBOPT_0x28: ST -Y,R19 LDD R30,Y+13 LDD R31,Y+13+1 ST -Y,R31 ST -Y,R30 JMP __put_G2 ;OPTIMIZER ADDED SUBROUTINE, CALLED 5 TIMES SUBOPT_0x29: LDD R26,Y+14 LDD R27,Y+14+1 SBIW R26,4 STD Y+14,R26 STD Y+14+1,R27 ADIW R26,4 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x2A: ST -Y,R30 LDD R30,Y+13 LDD R31,Y+13+1 ST -Y,R31 ST -Y,R30 JMP __put_G2 ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x2B: CALL __GETW1P STD Y+6,R30 STD Y+6+1,R31 ST -Y,R31 ST -Y,R30 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x2C: LDD R30,Y+13 LDD R31,Y+13+1 ST -Y,R31 ST -Y,R30 JMP __put_G2 ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x2D: __PUTD1S 6 __GETD2S 6 CALL __MULF12 __PUTD1S 2 RET ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x2E: CALL __PUTPARD1 CALL _log __GETD2S 4 CALL __MULF12 CALL __PUTPARD1 JMP _exp ;OPTIMIZER ADDED SUBROUTINE, CALLED 2 TIMES SUBOPT_0x2F: ST -Y,R30 CALL __lcd_write_data JMP __lcd_ready ;OPTIMIZER ADDED SUBROUTINE, CALLED 3 TIMES SUBOPT_0x30: CALL __long_delay_G5 LDI R30,LOW(48) ST -Y,R30 JMP __lcd_init_write_G5 ;OPTIMIZER ADDED SUBROUTINE, CALLED 3 TIMES SUBOPT_0x31: ST -Y,R30 CALL __lcd_write_data JMP __long_delay_G5 _strlen: ld r26,y+ ld r27,y+ clr r30 clr r31 __strlen0: ld r22,x+ tst r22 breq __strlen1 adiw r30,1 rjmp __strlen0 __strlen1: ret _strlenf: clr r26 clr r27 ld r30,y+ ld r31,y+ __strlenf0: lpm r0,z+ tst r0 breq __strlenf1 adiw r26,1 rjmp __strlenf0 __strlenf1: movw r30,r26 ret _delay_ms: ld r30,y+ ld r31,y+ adiw r30,0 breq __delay_ms1 __delay_ms0: __DELAY_USW 0x7D0 wdr sbiw r30,1 brne __delay_ms0 __delay_ms1: ret __ftrunc: ldd r23,y+3 ldd r22,y+2 ldd r31,y+1 ld r30,y bst r23,7 lsl r23 sbrc r22,7 sbr r23,1 mov r25,r23 subi r25,0x7e breq __ftrunc0 brcs __ftrunc0 cpi r25,24 brsh __ftrunc1 clr r26 clr r27 clr r24 __ftrunc2: sec ror r24 ror r27 ror r26 dec r25 brne __ftrunc2 and r30,r26 and r31,r27 and r22,r24 rjmp __ftrunc1 __ftrunc0: clt clr r23 clr r30 clr r31 clr r22 __ftrunc1: cbr r22,0x80 lsr r23 brcc __ftrunc3 sbr r22,0x80 __ftrunc3: bld r23,7 ld r26,y+ ld r27,y+ ld r24,y+ ld r25,y+ cp r30,r26 cpc r31,r27 cpc r22,r24 cpc r23,r25 bst r25,7 ret _floor: rcall __ftrunc brne __floor1 __floor0: ret __floor1: brtc __floor0 ldi r25,0xbf __addfc: clr r26 clr r27 ldi r24,0x80 rjmp __addf12 __ADDW2R15: CLR R0 ADD R26,R15 ADC R27,R0 RET __ANEGW1: COM R30 COM R31 ADIW R30,1 RET __ANEGD1: COM R30 COM R31 COM R22 COM R23 SUBI R30,-1 SBCI R31,-1 SBCI R22,-1 SBCI R23,-1 RET __CWD1: MOV R22,R31 ADD R22,R22 SBC R22,R22 MOV R23,R22 RET __CBD2: MOV R27,R26 ADD R27,R27 SBC R27,R27 MOV R24,R27 MOV R25,R27 RET __MULW12U: MUL R31,R26 MOV R31,R0 MUL R30,R27 ADD R31,R0 MUL R30,R26 MOV R30,R0 ADD R31,R1 RET __GETW1P: LD R30,X+ LD R31,X SBIW R26,1 RET __GETD1P: LD R30,X+ LD R31,X+ LD R22,X+ LD R23,X SBIW R26,3 RET __PUTDP1: ST X+,R30 ST X+,R31 ST X+,R22 ST X,R23 RET __GETW1PF: LPM R0,Z+ LPM R31,Z MOV R30,R0 RET __PUTPARD1: ST -Y,R23 ST -Y,R22 ST -Y,R31 ST -Y,R30 RET __CDF2U: SET RJMP __CDF2U0 __CDF2: CLT __CDF2U0: RCALL __SWAPD12 RCALL __CDF1U0 __SWAPD12: MOV R1,R24 MOV R24,R22 MOV R22,R1 MOV R1,R25 MOV R25,R23 MOV R23,R1 __SWAPW12: MOV R1,R27 MOV R27,R31 MOV R31,R1 __SWAPB12: MOV R1,R26 MOV R26,R30 MOV R30,R1 RET _frexp: LD R26,Y+ LD R27,Y+ LD R30,Y+ LD R31,Y+ LD R22,Y+ LD R23,Y+ BST R23,7 LSL R22 ROL R23 CLR R24 SUBI R23,0x7E SBC R24,R24 ST X+,R23 ST X,R24 LDI R23,0x7E LSR R23 ROR R22 BRTS __ANEGF1 RET _ldexp: LD R26,Y+ LD R27,Y+ LD R30,Y+ LD R31,Y+ LD R22,Y+ LD R23,Y+ BST R23,7 LSL R22 ROL R23 ADD R23,R26 LSR R23 ROR R22 BRTS __ANEGF1 RET __ANEGF1: SBIW R30,0 SBCI R22,0 SBCI R23,0 BREQ __ANEGF10 SUBI R23,0x80 __ANEGF10: RET __REPACK: LDI R21,0x80 EOR R21,R23 BRNE __REPACK0 PUSH R21 RJMP __ZERORES __REPACK0: CPI R21,0xFF BREQ __REPACK1 LSL R22 LSL R0 ROR R21 ROR R22 MOV R23,R21 RET __REPACK1: PUSH R21 TST R0 BRMI __REPACK2 RJMP __MAXRES __REPACK2: RJMP __MINRES __UNPACK: LDI R21,0x80 MOV R1,R25 AND R1,R21 LSL R24 ROL R25 EOR R25,R21 LSL R21 ROR R24 __UNPACK1: LDI R21,0x80 MOV R0,R23 AND R0,R21 LSL R22 ROL R23 EOR R23,R21 LSL R21 ROR R22 RET __CFD1: PUSH R21 RCALL __UNPACK1 CPI R23,0x80 BRLO __CFD10 CPI R23,0xFF BRCC __CFD10 RJMP __ZERORES __CFD10: LDI R21,22 SUB R21,R23 BRPL __CFD11 NEG R21 CPI R21,8 BRLO __CFD17 SER R30 SER R31 SER R22 LDI R23,0x7F RJMP __CFD15 __CFD17: CLR R23 TST R21 BREQ __CFD15 __CFD18: LSL R30 ROL R31 ROL R22 ROL R23 DEC R21 BRNE __CFD18 RJMP __CFD15 __CFD11: CLR R23 __CFD12: CPI R21,8 BRLO __CFD13 MOV R30,R31 MOV R31,R22 MOV R22,R23 SUBI R21,8 RJMP __CFD12 __CFD13: TST R21 BREQ __CFD15 __CFD14: LSR R23 ROR R22 ROR R31 ROR R30 DEC R21 BRNE __CFD14 __CFD15: TST R0 BRPL __CFD16 RCALL __ANEGD1 __CFD16: POP R21 RET __CDF1U: SET RJMP __CDF1U0 __CDF1: CLT __CDF1U0: SBIW R30,0 SBCI R22,0 SBCI R23,0 BREQ __CDF10 CLR R0 BRTS __CDF11 TST R23 BRPL __CDF11 COM R0 RCALL __ANEGD1 __CDF11: MOV R1,R23 LDI R23,30 TST R1 __CDF12: BRMI __CDF13 DEC R23 LSL R30 ROL R31 ROL R22 ROL R1 RJMP __CDF12 __CDF13: MOV R30,R31 MOV R31,R22 MOV R22,R1 PUSH R21 RCALL __REPACK POP R21 __CDF10: RET __SWAPACC: MOV R21,R30 MOV R30,R26 MOV R26,R21 MOV R21,R31 MOV R31,R27 MOV R27,R21 MOV R21,R22 MOV R22,R24 MOV R24,R21 MOV R21,R23 MOV R23,R25 MOV R25,R21 MOV R21,R0 MOV R0,R1 MOV R1,R21 RET __UADD12: ADD R30,R26 ADC R31,R27 ADC R22,R24 RET __NEGMAN1: COM R30 COM R31 COM R22 SUBI R30,-1 SBCI R31,-1 SBCI R22,-1 RET __SUBF12: PUSH R21 RCALL __UNPACK CPI R25,0x80 BREQ __ADDF129 LDI R21,0x80 EOR R1,R21 RJMP __ADDF120 __ADDF12: PUSH R21 RCALL __UNPACK CPI R25,0x80 BREQ __ADDF129 __ADDF120: CPI R23,0x80 BREQ __ADDF128 __ADDF121: MOV R21,R23 SUB R21,R25 BRVS __ADDF129 BRPL __ADDF122 RCALL __SWAPACC RJMP __ADDF121 __ADDF122: CPI R21,24 BRLO __ADDF123 CLR R26 CLR R27 CLR R24 __ADDF123: CPI R21,8 BRLO __ADDF124 MOV R26,R27 MOV R27,R24 CLR R24 SUBI R21,8 RJMP __ADDF123 __ADDF124: TST R21 BREQ __ADDF126 __ADDF125: LSR R24 ROR R27 ROR R26 DEC R21 BRNE __ADDF125 __ADDF126: MOV R21,R0 EOR R21,R1 BRMI __ADDF127 RCALL __UADD12 BRCC __ADDF129 ROR R22 ROR R31 ROR R30 INC R23 BRVC __ADDF129 RJMP __MAXRES __ADDF128: RCALL __SWAPACC __ADDF129: RCALL __REPACK POP R21 RET __ADDF127: SUB R30,R26 SBC R31,R27 SBC R22,R24 BREQ __ZERORES BRCC __ADDF1210 COM R0 RCALL __NEGMAN1 __ADDF1210: TST R22 BRMI __ADDF129 LSL R30 ROL R31 ROL R22 DEC R23 BRVC __ADDF1210 __MINRES: SER R30 SER R31 LDI R22,0x7F SER R23 POP R21 RET __ZERORES: CLR R30 CLR R31 CLR R22 CLR R23 POP R21 RET __MAXRES: SER R30 SER R31 LDI R22,0x7F LDI R23,0x7F POP R21 RET __MULF12: PUSH R21 RCALL __UNPACK CPI R23,0x80 BREQ __ZERORES CPI R25,0x80 BREQ __ZERORES EOR R0,R1 SEC ADC R23,R25 BRVC __MULF124 BRLT __ZERORES __MULF125: TST R0 BRMI __MINRES RJMP __MAXRES __MULF124: PUSH R19 PUSH R20 CLR R1 CLR R19 CLR R20 CLR R21 LDI R25,24 __MULF120: LSL R19 ROL R20 ROL R21 ROL R30 ROL R31 ROL R22 BRCC __MULF121 ADD R19,R26 ADC R20,R27 ADC R21,R24 ADC R30,R1 ADC R31,R1 ADC R22,R1 __MULF121: DEC R25 BRNE __MULF120 POP R20 POP R19 TST R22 BRMI __MULF122 LSL R21 ROL R30 ROL R31 ROL R22 RJMP __MULF123 __MULF122: INC R23 BRVS __MULF125 __MULF123: RCALL __REPACK POP R21 RET __DIVF21: PUSH R21 RCALL __UNPACK CPI R23,0x80 BRNE __DIVF210 TST R1 __DIVF211: BRPL __MAXRES RJMP __MINRES __DIVF210: CPI R25,0x80 BRNE __DIVF218 __DIVF217: RJMP __ZERORES __DIVF218: EOR R0,R1 SEC SBC R25,R23 BRVC __DIVF216 BRLT __DIVF217 TST R0 RJMP __DIVF211 __DIVF216: MOV R23,R25 LSR R22 ROR R31 ROR R30 LSR R24 ROR R27 ROR R26 PUSH R20 CLR R1 CLR R20 CLR R21 LDI R25,24 __DIVF212: CP R26,R30 CPC R27,R31 CPC R24,R22 BRLO __DIVF213 SUB R26,R30 SBC R27,R31 SBC R24,R22 SEC RJMP __DIVF214 __DIVF213: CLC __DIVF214: ROL R1 ROL R20 ROL R21 ROL R26 ROL R27 ROL R24 DEC R25 BRNE __DIVF212 MOV R30,R1 MOV R31,R20 MOV R22,R21 LSR R26 ADC R30,R25 ADC R31,R25 ADC R22,R25 POP R20 TST R22 BRMI __DIVF215 LSL R30 ROL R31 ROL R22 DEC R23 BRVS __DIVF217 __DIVF215: RCALL __REPACK POP R21 RET __CMPF12: TST R25 BRMI __CMPF120 TST R23 BRMI __CMPF121 CP R25,R23 BRLO __CMPF122 BRNE __CMPF121 CP R26,R30 CPC R27,R31 CPC R24,R22 BRLO __CMPF122 BREQ __CMPF123 __CMPF121: CLZ CLC RET __CMPF122: CLZ SEC RET __CMPF123: SEZ CLC RET __CMPF120: TST R23 BRPL __CMPF122 CP R25,R23 BRLO __CMPF121 BRNE __CMPF122 CP R30,R26 CPC R31,R27 CPC R22,R24 BRLO __CMPF122 BREQ __CMPF123 RJMP __CMPF121 __CPD10: SBIW R30,0 SBCI R22,0 SBCI R23,0 RET __CPW02: CLR R0 CP R0,R26 CPC R0,R27 RET __CPD20: SBIW R26,0 SBCI R24,0 SBCI R25,0 RET __CPD02: CLR R0 CP R0,R26 CPC R0,R27 CPC R0,R24 CPC R0,R25 RET __CPD12: CP R30,R26 CPC R31,R27 CPC R22,R24 CPC R23,R25 RET __SAVELOCR6: ST -Y,R21 __SAVELOCR5: ST -Y,R20 __SAVELOCR4: ST -Y,R19 __SAVELOCR3: ST -Y,R18 __SAVELOCR2: ST -Y,R17 ST -Y,R16 RET __LOADLOCR6: LDD R21,Y+5 __LOADLOCR5: LDD R20,Y+4 __LOADLOCR4: LDD R19,Y+3 __LOADLOCR3: LDD R18,Y+2 __LOADLOCR2: LDD R17,Y+1 LD R16,Y RET ;END OF CODE MARKER __END_OF_CODE: