英锐恩单片机论坛,Microchip单片机,模拟器件,接口电路,麦肯单片机,单片机应用交流

 找回密码
 立即注册
搜索
电子烟方案单片机单片机开发深圳单片机开发
单片机方案国产单片机8位单片机电子烟方案开发
查看: 6360|回复: 2

PIC16F84A MemoSound Game 【转】

[复制链接]
发表于 2012-8-21 11:51:17 | 显示全部楼层 |阅读模式
/*
* Project : memosound
* Author : Bruno Gavand
* Date : August, 2006
* Description : Sound & Light memorization game
*
* Target : PIC16F84A @ 8 MHz
* Flags : HS oscillator, no watchdog, no power up timer
*
* IDE : mikroC V6.0
*
* the player has to memorize and play back a melody :
* the PIC creates a new melody for each new game
* a melody is up to 63 steps
* each step is a tone corresponding to a color
* there are 4 tones (A, B, C, D) and then 4 LEDs (red, green , orange, yellow)
*
* start-up : the PIC plays a welcome melody and secretly creates the new melody
* the PIC plays the first step of the melody, and the player have to play it back
* if it is the good one, the PIC plays the melody from the beginnig with one more step
* the player have to repeat the same melody
* if the player fails, an error melody is played and the PIC plays the same melody again
* when all 63 steps of the melody are correctly played back by the player,
* the PIC plays a win melody and creates a new one.
* at any time, the player can press two buttons at a time to give up with the current melody
* and start with a new one.
*
* RA0...RA3 : LEDs
* RB0 : Piezzo buzzer
* RB4...RB7 : Buttons
*
* see more details on  *
*/

/*
* macro definitions
*/
#define NBFREQ  7                       // size of frequency table
#define NBCYCLES(freq)  (2000/f)        // duration of a sound

#define EEPROM_SIZE     64              // size of P16F84A EEPROM : steps are stored in EEPROM
#define NBSTEPS         (EEPROM_SIZE - 2)       // maximum number of steps
#define ADDR_NBSTEPS    (EEPROM_SIZE - 2)       // address in EEPROM of the step counter
#define ADDR_SPEED      (EEPROM_SIZE - 1)       // address in EEPROM of the game speed

/*
* frequency table : periods in thousands of ms
*/
const unsigned char     t_period[NBFREQ] =
        {
        132,
        148,
        165,
        176,
        198,
        220,
        247
        } ;

unsigned char   speed ;         // game speed

/*
* delays are made as function instead of macro
* to save ROM space
*
* 1 second delay
*/
void    delay1000ms()
        {
        Delay_ms(1000) ;
        }

/*
* 10 ms delay
*/
void    delay10ms()
        {
        Delay_ms(10) ;
        }

/*
* play one sound with LED
*
* s : index of the sound in frequency table
* d : duration of the sound in numbers of periods
* t : duration of silence after the sound (to be multiplied by 10 ms)
*/
void    playSound(unsigned char s, unsigned char d, unsigned char n, unsigned char t)
        {
        unsigned char c ;
        
        c = t_period ;
        PORTA = 1 << (s & 3) ;          // light LED corresponding to the sound index
        while(n--)
                {
                while(d--)
                        {
                        unsigned char cc ;
                        
                        PORTB.F0 ^= 1 ;
                        for(cc = 0 ; cc < c ; cc++) Delay_us(1)  ;
                        }
                }
        PORTA = 0 ;                     // turn LED off
        PORTB.F0 = 0 ;                  // turn loudspeaker off
        while(t--) delay10ms() ;        // do the silence if needed
        }

/*
* play the error melody, all tones in descending order
*/
void    playError()
        {
        unsigned char i ;

        for(i = 0 ; i < NBFREQ ; i++)
                {
                playSound(i, 50, 1, 0) ;
                }
        delay1000ms() ;
        }

/*
* play the welcome melody, all tones in ascending order
*/
void    playWelcome()
        {
        unsigned char i ;

        for(i = NBFREQ ; i > 0 ; i--)
                {
                playSound(i - 1, 50, 1, 0) ;
                }
        }

/*
* fill EEPROM with a new melody
*/
void    fillEEPROM()
        {
        unsigned char   i ;

        for(i = 0 ; i < NBSTEPS ; i++)          // for all melody steps
                {
                EEPROM_Write(i, rand() % 4) ;   // writes a random index from 0 to 3 in EEPROM location
                }
        EEPROM_Write(ADDR_NBSTEPS, 0) ;         // reset the current step number
        }

/*
* increment melody step number
*
* return 0 if the player won
* return 1 otherwise
*/
unsigned char   nextStep()
        {
        unsigned char   s ;

        s = EEPROM_Read(ADDR_NBSTEPS) ;         // read current step number from EEPROM
        s++ ;                                   // next one
        if(s == NBSTEPS)                        // is it the maximum step number ?
                {
                return(0) ;                     // yes, player has won
                }

        delay10ms() ;                           // waits a little bit

        INTCON.RBIE = 0 ;                       // disable portb interrupt
        INTCON.RBIF = 0 ;                       // clear pending interrupt
        EEPROM_Write(ADDR_NBSTEPS, s) ;         // no, write new step

        delay10ms() ;                           // waits a little bit

        return(1) ;                             // not won yet
        }

/*
* play a step
*
* a : index in EEPROM of the step to play
*/
void    playEEPROM(unsigned char a)
        {
        unsigned char   n ;

        n = EEPROM_Read(a) ;                                    // read frequency index from EEPROM
        playSound(n, t_period[NBFREQ - 1 - n], speed, 10) ;     // play corresponding sound
        }

/*
* most important routine,
* verify if player's entry matches melody stored in EEPROM
*/
unsigned char   verifEEPROM()
        {
        unsigned char   i, s, v, b ;

        s = EEPROM_Read(ADDR_NBSTEPS) ;         // read current player's level
        for(i = 0 ; i < s ; i++)                // for each level
                {
                INTCON.RBIF = 0 ;               // clear PORTB on change interrupt flag
                INTCON.RBIE = 1 ;               // enables PORTB on change interrupt
                INTCON.GIE = 0 ;                // do not call interrupt routine at wake up
                asm { sleep } ;                 // go to sleep mode, and low power consomption

                /*
                 * when user press at least one key, the PIC wakes up
                 * and continues in sequence here
                 */
                v = EEPROM_Read(i) ;            // get next tone of the melody

                while((PORTB & 0xf0) != 0xf0)   // while a key is still pressed
                        {
                        b = PORTB & 0xf0 ;                      // get keys status
                        if(b == 0b01110000) b = 0 ;             // decode keys, and get tone number
                        else if(b == 0b10110000) b = 1 ;
                        else if(b == 0b11010000) b = 2 ;
                        else if(b == 0b11100000) b = 3 ;
                        else if(b == 0b11000000)                // is speed mode selected ?
                                {
                                delay1000ms() ;                 // debounce with delay
                                for(;;)                         // enter forever selection loop
                                        {
                                        for(b = 0 ; b < 4 ; b++)        // for all LEDS
                                                {
                                                PORTA = 1 << (b & 3) ;          // light LED
                                                for(s = 0 ; s < 200 ; s++)      // for a little while
                                                        {
                                                        if((PORTB & 0xf0) != 0xf0) // if a key is pressed
                                                                {
                                                                PORTA = 0 ;             // clear LEDs
                                                                speed = b + 1 ;         // compute speed
                                                                EEPROM_Write(ADDR_SPEED, speed) ; // store speed in EEPROM

                                                                delay1000ms() ;         // wait a little bit

                                                                return(0) ;             // resume melody
                                                                }
                                                        delay10ms() ;
                                                        }
                                                }
                                        }
                                }
                        else if(b == 0b00110000)                // is melody reset selected ?
                                {
                                PORTA = 0xf ;                   // understood, light all LEDs
                                delay1000ms() ;                 // wait one second
                                PORTA = 0 ;                     // clear all LEDs

                                return(2) ;                     // code 2 to prevent error melody to be played
                                }

                        playSound(b, t_period[NBFREQ - 1 - b], 1, 0) ; // play the sound corresponding to the key pressed by the player
                        }

                delay10ms() ;                   // debounce keys
                rand() ;                        // usefull to get more unpredictable melodies

                if(b != v)                      // did the player gave the wrong tone ?
                        {
                        playError() ;           // yes, play error melody
                        return(0) ;             // code 2 for player's memory failure about this tone
                        }
                }

        return(1) ;                             // code 1 for correct player's memory for this tone
        }

/*
* play all melody according to player's level
*/

void    playMusic()
        {
        unsigned char   i, s ;

        s = EEPROM_Read(ADDR_NBSTEPS) ;         // get player's level
        for(i = 0 ; i < s ; i++)                // for each level
                {
                playEEPROM(i) ;                 // play the tone of the melody
                }
        }

/*
* program entry
*/
void main()
        {
        unsigned char r ;

        TRISA = 0 ;     // PORTA is output
        PORTA = 0 ;     // clear output

        TRISB = 0xf0 ;  // high nibble is input for keys, low nibble is output
        PORTB = 0 ;     // clear output

        OPTION_REG &= 0b01111111 ;      // weak pull-up on PORTB

        speed = EEPROM_Read(ADDR_SPEED) ;       // get game speed

        PlayWelcome() ;                         // play welcome melody
        delay1000ms() ;                         // 1 second delay before game start

        for(;;)                                 // forerver
                {
                fillEEPROM() ;                  // fill EEPROM with new melody

                while(nextStep())               // next step in melody
                        {
                        do
                                {
                                playMusic() ;   // play melody to current step
                                }
                        while((r = verifEEPROM()) == 0) ;       // until player repeat it correctly

                        if(r == 2)              // player asked for new melody
                                {
                                break ;
                                }

                        delay1000ms() ;         // 1 second delay before next step
                        }

                if(r == 1)                      // player repeated all steps correctly
                        {
                        PlayWelcome() ;         // play win melody
                        PlayWelcome() ;
                        PlayWelcome() ;
                        PlayWelcome() ;

                        delay1000ms() ;         // 1 second delay befor new game
                        }
                }
        }

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

小黑屋|公司首页|Microchip单片机,模拟器件,接口电路,麦肯单片机,单片机应用交流 ( 粤ICP备09008620号 )

GMT+8, 2024-3-29 12:53 , Processed in 0.063985 second(s), 26 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表