Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // A video demonstration of this project can be found here: https://bit.ly/3gY4HGI
- /*
- This rules of this dice game can be found on the wiki page titled
- "Pigs Dice Game." The following parts were used in the making of this project:
- [1] PIC18F4520
- [7] 20mA red LEDs
- [7] 220 Ohm resistors
- [2] Standard push buttons
- [2] 10k Ohm resistors
- [1] 10k potentiometer
- [1] 5v regulator (L7805CV)
- [2] 10 microfarad capacitors
- [1] 9v battery
- [1] LCD display (HD44780U)
- [3] breadboards
- */
- #include <xc.h>
- #include <pic18f4520.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <stdbool.h>
- #include <stdint.h>
- #include "DiceGameConfig.h"
- #define CLEAR 0x01
- #define SET_FUNCTION 0x3C
- #define DISPLAY_OFF 0x08 //note that this also sets the cursor off as well
- #define INCREMENT 0x06 //note that this also sets Shift to 0
- #define DISPLAY_ON 0x0C // note that the cursor is still off
- #define SET_8BITS 0x30
- #define LCD_DATA_PINS LATD
- #define LCD_RS LATEbits.LE0
- #define LCD_RW LATEbits.LE1
- #define LCD_E LATEbits.LE2
- #define ROLL_BUTTON PORTCbits.RC2
- #define PASS_BUTTON PORTCbits.RC1
- void bitSetupADC(void);
- void bitSetupOscillator(void);
- void bitSetupLEDs(void);
- void bitSetupButtons(void);
- void bitSetupLCD(void);
- void initLCD(void);
- void LCDClock(void);
- void handleLCDCommands(uint8_t);
- void LCDPrintChar(uint8_t);
- void LCDPrintString();
- uint8_t intToLCDCharacters(int num);
- void delay(int milliseconds);
- void updateScoreBoard(int num);
- void handleGame(int landedDiceVal);
- void handlePreGame(void);
- void runLEDs(void);
- void rollDice(int *pLandedDiceVal);
- void displayDice(int num);
- void changePlayersTurn(void);
- int makeRandomNumber(void);
- void playWinningGraphics(int winningPlayer);
- void handleButtonPresses(void);
- void resetGame(void);
- bool playerOnesTurn = false;
- bool playerTwosTurn = false;
- bool combineScore = false;
- bool changingTurn = false;
- bool startOfGame = true;
- bool rollButtonPressed = false;
- bool passButtonPressed = false;
- int playerOnesScore = 0;
- int playerTwosScore = 0;
- int playerOnesPotentialScore = 0;
- int playerTwosPotentialScore = 0;
- void main(void)
- {
- int landedDiceVal;
- int *pLandedDiceVal;
- pLandedDiceVal = &landedDiceVal;
- bitSetupADC();
- bitSetupOscillator();
- bitSetupLEDs();
- bitSetupButtons();
- bitSetupLCD();
- initLCD();
- while(1)
- {
- while(startOfGame == true)
- {
- handlePreGame();
- }
- handleButtonPresses();
- if(ROLL_BUTTON == 1 && rollButtonPressed == true)
- {
- rollDice(pLandedDiceVal);
- displayDice(landedDiceVal);
- handleGame(landedDiceVal);
- rollButtonPressed = false;
- }
- else if(PASS_BUTTON == 1 && passButtonPressed == true)
- {
- changingTurn = true;
- changePlayersTurn();
- delay(500);
- passButtonPressed = false;
- }
- }
- }
- void bitSetupADC()
- {
- TRISBbits.RB0 = 1;
- ADCON0bits.CHS = 0b1100;
- ADCON0bits.ADON = 1;
- ADCON1bits.VCFG0 = 0;
- ADCON1bits.VCFG1 = 0;
- ADCON1bits.PCFG = 0b0001;
- ADCON2bits.ADFM = 1;
- ADCON2bits.ACQT = 0x04;
- ADCON2bits.ADCS = 0x04;
- }
- void bitSetupOscillator()
- {
- OSCCONbits.IRCF = 0b111; //set internal oscillator to 8MHz
- OSCCONbits.SCS = 0b10;
- while(OSCCONbits.IOFS != 1);// wait until the oscillator is stable
- }
- void bitSetupLEDs()
- {
- TRISA = 0x00;
- LATA = 0x00;
- }
- void bitSetupButtons()
- {
- TRISCbits.RC3 = 1;
- TRISCbits.RC2 = 1;
- }
- void bitSetupLCD()
- {
- TRISD = 0x00; //sets LCD_DATA_PINS to output
- TRISEbits.RE0 = 0; //sets LCD_RS to output
- TRISEbits.RE1 = 0; // sets LCD_RW to output
- TRISEbits.RE2 = 0; // sets LCD_E to output
- //init RS, RW, E, and the data pins to low
- LCD_RS = 0;
- LCD_RW = 0;
- LCD_E = 0;
- LCD_DATA_PINS = 0x00;
- }
- /*
- LCDClock is called whenever data is sent to the LCD screen. In the data sheet,
- it is shown that the data is transfered on the falling edge of the E pin.
- Therefore, the function enables the E pin to 1, and then shortly after, to 0.
- */
- void LCDClock()
- {
- LCD_E = 1;
- __delay_ms(1);
- LCD_E = 0;
- __delay_ms(1);
- }
- /*
- handleLCDCommands is called whenever you want to send a specific command
- to the LCD, such as CLEAR or SET_FUNCTION. Note that this function is
- not writing to the LCD, which is why the RS pin is low;
- */
- void handleLCDCommands(uint8_t command)
- {
- LCD_RS = 0;
- LCD_RW = 0;
- LCD_DATA_PINS = command;
- LCDClock();
- __delay_ms(10);
- }
- /*
- initLCD initializes the LCD. In the data sheet, there is a very specific way
- to do it, so make sure that if you are using a different LCD, you must adjust
- accordingly.
- */
- void initLCD()
- {
- LCD_RS = 0;
- LCD_RW = 0;
- __delay_ms(50);
- handleLCDCommands(SET_8BITS);
- __delay_ms(10);
- handleLCDCommands(SET_8BITS);
- __delay_ms(1);
- handleLCDCommands(SET_8BITS);
- handleLCDCommands(SET_FUNCTION);
- handleLCDCommands(DISPLAY_OFF);
- handleLCDCommands(CLEAR);
- handleLCDCommands(INCREMENT);
- handleLCDCommands(DISPLAY_ON);
- }
- /*
- LCDSetCursor allows you to set a specific place on the LCD screen to write too.
- for example, if you would like a character to show up on the first row on the
- second column, you would pass in 0 and 1 to the function.
- */
- uint8_t LCDSetCursor(uint8_t xPos, uint8_t yPos)
- {
- if(yPos == 1)
- {
- xPos += 0x40;
- }
- handleLCDCommands(0x80 | xPos);
- return xPos;
- }
- /*
- LCDPrintChar allows you to write one uint8_t to the LCD screen. Note that you
- cant simply pass in an 8 (LCDPrintChat(8)) as this is considered 8 in binary
- and spits out a funky character. I have made a function, however, to convert
- the integer into your desired character. That function is located on line 278.
- */
- void LCDPrintChar(uint8_t x)
- {
- LCD_RS = 1;
- LCD_RW = 0;
- LCD_DATA_PINS = x;
- LCDClock();
- }
- /*
- LCDPrintString allows you to write a string, such as "hello world" to the LCD screen.
- */
- void LCDPrintString(const char *str)
- {
- uint16_t i = 0;
- do
- {
- LCDPrintChar(str[i]);
- i++;
- }while(str[i] != '\0');
- }
- /*
- the makeRandomNumber function returns a random number based on an
- analog signal from a floating pin.
- */
- int makeRandomNumber()
- {
- int randomNumber;
- ADCON0bits.GODONE = 1;
- while(ADCON0bits.GODONE);
- randomNumber = (ADRESH << 8) | (ADRESL);
- while(randomNumber >= 6)
- {
- randomNumber = randomNumber - 6;
- }// maps the value of the ADC (0-1024) to (0-6)
- return randomNumber;
- }
- /*
- delay allows you to pass in high values, such as 60000 (1 minute) without
- having any bugs with the __delay_ms function.
- */
- void delay(int milliseconds)
- {
- for(int i = 0; i < milliseconds/50; i++)
- __delay_ms(50);
- }
- /*
- intToLCDCharacter's purpose is to turn an integer into a byte that displays
- the integer's value onto the LCD screen. For example, in the data sheet, to display
- the number 0, you must send following byte: 0b00110000
- this turns out to be 48 in decimal, and the numbers increment by 1 from there,
- which explains the num + 48.
- */
- uint8_t intToLCDCharacters(int num)
- {
- num = num + 48;
- return num;
- }
- /*
- This function allows you to display any dice number you want by
- passing in a number between 0-5.
- */
- void displayDice(int num)
- {
- int diceNumbers[6] = {0b00010000, 0b00100010, 0b00110010,
- 0b01100011, 0b01110011, 0b01101111};
- LATA = diceNumbers[num];
- delay(2500);
- LATA = 0;
- }
- /*
- runLEDs displays the waiting animation on the LED dice.
- */
- void runLEDs()
- {
- int specificLED = 1;
- for(int i = 0; i < 21; i++)
- {
- LATA = specificLED;
- delay(100);
- specificLED = specificLED * 2;
- if(specificLED > 64)
- {
- specificLED = 1;
- }
- }
- LATA = 0;
- }
- /*
- rollDice puts all the functions to use and handles everything that is needed
- to roll and display the dice.
- */
- void rollDice(int *pLandedDiceVal)
- {
- runLEDs();
- *pLandedDiceVal = makeRandomNumber();
- }
- /*
- the handlePreGame function handles who goes first.
- */
- void handlePreGame()
- {
- bool rollingDice;
- bool tie = true;
- int playerOnesRoll;
- int playerTwosRoll;
- int landedDiceVal;
- int *pLandedDiceVal;
- pLandedDiceVal = &landedDiceVal;
- do
- {
- LCDSetCursor(0,0);
- LCDPrintString("Player one");
- LCDSetCursor(0,1);
- LCDPrintString("please roll");
- while(ROLL_BUTTON != 0);
- rollingDice = true;
- rollDice(pLandedDiceVal);
- displayDice(landedDiceVal);
- playerOnesRoll = landedDiceVal;
- LCDSetCursor(0,0);
- LCDPrintString("Player two");
- LCDSetCursor(0,1);
- LCDPrintString("please roll");
- while(ROLL_BUTTON != 0);
- rollingDice = true;
- rollDice(pLandedDiceVal);
- displayDice(landedDiceVal);
- playerTwosRoll = landedDiceVal;
- if(playerTwosRoll > playerOnesRoll)
- {
- handleLCDCommands(CLEAR);
- LCDSetCursor(0,0);
- LCDPrintString("Player two goes");
- LCDSetCursor(0,1);
- LCDPrintString("first");
- delay(2500);
- handleLCDCommands(CLEAR);
- tie = false;
- LCDSetCursor(0,0);
- LCDPrintString("Player 1: 00");
- LCDSetCursor(0,1);
- LCDPrintString("Player 2:->00+00");
- playerTwosTurn = true;
- startOfGame = false;
- }
- else if(playerOnesRoll > playerTwosRoll)
- {
- handleLCDCommands(CLEAR);
- LCDSetCursor(0,0);
- LCDPrintString("Player one goes");
- LCDSetCursor(0,1);
- LCDPrintString("first");
- delay(2500);
- handleLCDCommands(CLEAR);
- tie = false;
- LCDSetCursor(0,0);
- LCDPrintString("Player 1:->00+00");
- LCDSetCursor(0,1);
- LCDPrintString("Player 2: 00");
- playerOnesTurn = true;
- startOfGame = false;
- }
- else
- {
- handleLCDCommands(CLEAR);
- LCDSetCursor(0,0);
- LCDPrintString("Y'all tied");
- delay(2000);
- handleLCDCommands(CLEAR);
- }
- }while(tie);
- }
- /*
- the updateScoareBoard function updates the current players score.
- */
- void updateScoreBoard(int num)
- {
- int firstDigit;
- int secondDigit;
- //this first if/else statement creates two integers that can be passed
- //into the intToLCDCharacters function, which is then passed in the
- //LCDPrintChar function.
- if(num > 9)
- {
- firstDigit = num/10;
- secondDigit = num-(firstDigit*10);
- }
- else
- {
- firstDigit = 0;
- secondDigit = num;
- }
- if(playerOnesTurn)
- {
- if(combineScore == true)
- {
- LCDSetCursor(11,0);
- combineScore = false;
- }
- else
- {
- LCDSetCursor(14,0);
- }
- }
- else
- {
- if(combineScore == true)
- {
- LCDSetCursor(11,1);
- combineScore = false;
- }
- else
- {
- LCDSetCursor(14,1);
- }
- }
- LCDPrintChar(intToLCDCharacters(firstDigit));
- LCDPrintChar(intToLCDCharacters(secondDigit));
- }
- /*
- The handleGame function runs the rules of the game and makes sure that
- when the play rolls a one or the player reaches a score of 100, then the
- game responds accordingly. This function also increments the players
- potential score for that turn.
- */
- void handleGame(int landedDiceVal)
- {
- if(playerOnesTurn)
- {
- if(landedDiceVal == 0) //if they player rolls a one, then their score
- { //resets and it becomes the other players turn.
- playerOnesPotentialScore = 0;
- changingTurn = true;
- changePlayersTurn();
- }
- else
- {
- playerOnesPotentialScore = playerOnesPotentialScore + landedDiceVal + 1;
- updateScoreBoard(playerOnesPotentialScore);
- }
- if((playerOnesPotentialScore + playerOnesScore) >= 100)
- {
- playWinningGraphics(1);
- resetGame();
- }
- }
- else
- {
- if(landedDiceVal == 0)
- {
- playerTwosPotentialScore = 0;
- changingTurn = true;
- changePlayersTurn();
- }
- else
- {
- playerTwosPotentialScore = playerTwosPotentialScore + landedDiceVal + 1;
- updateScoreBoard(playerTwosPotentialScore);
- }
- if((playerTwosPotentialScore + playerTwosScore) >= 100)
- {
- playWinningGraphics(2);
- resetGame();
- }
- }
- }
- /*
- The changePlayersTurn function changes the display to show the correct scores
- of the players and indicates who's turn it is.
- */
- void changePlayersTurn()
- {
- while(changingTurn)
- {
- if(playerOnesTurn)
- {
- playerOnesScore = playerOnesScore + playerOnesPotentialScore;
- combineScore = true;
- LCDSetCursor(9,0);
- LCDPrintString(" ");
- LCDSetCursor(13,0);
- LCDPrintString(" ");
- LCDSetCursor(9,1);
- LCDPrintString("->");
- LCDSetCursor(13,1);
- LCDPrintString("+00");
- updateScoreBoard(playerOnesScore);
- }
- else
- {
- playerTwosScore = playerTwosScore + playerTwosPotentialScore;
- combineScore = true;
- LCDSetCursor(9,1);
- LCDPrintString(" ");
- LCDSetCursor(13,1);
- LCDPrintString(" ");
- LCDSetCursor(9,0);
- LCDPrintString("->");
- LCDSetCursor(13,0);
- LCDPrintString("+00");
- updateScoreBoard(playerTwosScore);
- }
- playerOnesPotentialScore = 0;
- playerTwosPotentialScore = 0;
- playerOnesTurn = !playerOnesTurn;
- playerTwosTurn = !playerTwosTurn;
- changingTurn = false;
- }
- }
- /*
- the playWinningGraphics function displays the winning player on the LCD screen
- and animates the LEDs before restarting the entire game.
- */
- void playWinningGraphics(int winningPlayer)
- {
- handleLCDCommands(CLEAR);
- if(winningPlayer == 1)
- {
- LCDPrintString("PLAYER ONE WINS!");
- }
- else
- {
- LCDPrintString("PLAYER TWO WINS!");
- }
- for(int i = 0; i < 3; i++)
- {
- runLEDs();
- }
- handleLCDCommands(CLEAR);
- startOfGame = true;
- }
- void handleButtonPresses()
- {
- if(ROLL_BUTTON == 0)
- {
- rollButtonPressed = true;
- passButtonPressed = false;
- }
- else if(PASS_BUTTON == 0)
- {
- rollButtonPressed = false;
- passButtonPressed = true;
- }
- }
- void resetGame()
- {
- playerOnesScore = 0;
- playerTwosScore = 0;
- playerOnesPotentialScore = 0;
- playerTwosPotentialScore = 0;
- }
Add Comment
Please, Sign In to add comment