#include "main.h"
#include "ssd1306.h"
#include <stdio.h>
/* ================= SPI ================= */
SPI_HandleTypeDef hspi1;
/* ================= OLED I2C ================= */
I2C_HandleTypeDef hi2c1;
/* ================= COMMAND ================= */
#define CMD_GAME_RUN 0x01
#define CMD_GAME_OVER 0x02
#define CMD_JUMP_SOUND 0x03
#define CMD_HIT_SOUND 0x04
/* ================= CS PIN ================= */
#define CS_PORT GPIOA
#define CS_PIN GPIO_PIN_4
/* ================= GAME ================= */
int dinoY, velocityY, cactusX;
uint32_t score, highScore;
uint8_t isJumping, gameOver;
#define GRAVITY 2
#define FRAME_DELAY 30
#define GROUND_Y 48
#define DINO_HEIGHT 10
char buf[20];
/* ================= SEND SPI ================= */
void Send_To_Slave(uint8_t cmd)
{
HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_RESET);
HAL_SPI_Transmit(&hspi1, &cmd, 1, 100);
HAL_GPIO_WritePin(CS_PORT, CS_PIN, GPIO_PIN_SET);
HAL_Delay(1); // penting untuk sync slave
}
/* ================= MAIN ================= */
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI1_Init();
MX_I2C1_Init();
ssd1306_Init();
HAL_GPIO_WritePin(GPIOA, CS_PIN, GPIO_PIN_SET);
ResetGame();
while (1)
{
if (!gameOver)
{
UpdateGame();
DrawGame();
Send_To_Slave(CMD_GAME_RUN);
}
else
{
DrawGameOver();
if (score > highScore)
highScore = score;
Send_To_Slave(CMD_GAME_OVER);
if (HAL_GPIO_ReadPin(JUMP_BTN_GPIO_Port, JUMP_BTN_Pin) ==
GPIO_PIN_RESET)
{
ResetGame();
HAL_Delay(300);
}
}
HAL_Delay(FRAME_DELAY);
}
}
/* ================= GAME LOGIC ================= */
void UpdateGame(void)
{
if (HAL_GPIO_ReadPin(JUMP_BTN_GPIO_Port, JUMP_BTN_Pin) ==
GPIO_PIN_RESET && !isJumping)
{
velocityY = -12;
isJumping = 1;
Send_To_Slave(CMD_JUMP_SOUND);
}
dinoY += velocityY;
velocityY += GRAVITY;
if (dinoY >= GROUND_Y)
{
dinoY = GROUND_Y;
velocityY = 0;
isJumping = 0;
}
cactusX -= (6 + score / 15);
if (cactusX < -10)
{
cactusX = 128;
score++;
}
if (cactusX < 25 && cactusX > 5 &&
(dinoY + DINO_HEIGHT) > 48)
{
gameOver = 1;
Send_To_Slave(CMD_HIT_SOUND);
}
}
/* ================= DRAW ================= */
void DrawGame(void)
{
ssd1306_Fill(Black);
ssd1306_DrawRectangle(10, dinoY,
20, dinoY + DINO_HEIGHT,
White);
ssd1306_FillRectangle(cactusX, 48,
cactusX + 8, 60,
White);
ssd1306_Line(0, 61, 127, 61, White);
sprintf(buf, "Sc:%lu", score);
ssd1306_SetCursor(0, 0);
ssd1306_WriteString(buf, Font_7x10, White);
sprintf(buf, "Hsc:%lu", highScore);
ssd1306_SetCursor(80, 0);
ssd1306_WriteString(buf, Font_7x10, White);
ssd1306_UpdateScreen();
}
void DrawGameOver(void)
{
ssd1306_Fill(Black);
}
ssd1306_SetCursor(30, 15);
ssd1306_WriteString("GAME OVER", Font_7x10, White);
sprintf(buf, "HighScore:%lu", highScore);
ssd1306_SetCursor(25, 35);
ssd1306_WriteString(buf, Font_7x10, White);
ssd1306_UpdateScreen();
}
/* ================= RESET ================= */
void ResetGame(void)
{
dinoY = GROUND_Y;
velocityY = 0;
cactusX = 128;
score = 0;
isJumping = 0;
gameOver = 0;
}
/* ================= SPI INIT ================= */
void MX_SPI1_Init(void)
{
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
HAL_SPI_Init(&hspi1);
}
/* ================= GPIO ================= */
void MX_GPIO_Init(void)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* CS */
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* BUTTON */
GPIO_InitStruct.Pin = JUMP_BTN_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(JUMP_BTN_GPIO_Port, &GPIO_InitStruct);
}
main.h
#ifndef __MAIN_H
#define __MAIN_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32g4xx_hal.h"
#include "ssd1306.h"
#include "ssd1306_fonts.h"
#include <stdio.h>
/* Definisi Pin Hardware */
#define JUMP_BTN_Pin GPIO_PIN_0
#define JUMP_BTN_GPIO_Port GPIOA
/* Konstanta Permainan */
#define GROUND_Y 44
#define DINO_WIDTH 15
#define DINO_HEIGHT 15
/* Prototipe Fungsi */
void SystemClock_Config(void);
void MX_GPIO_Init(void);
void MX_I2C1_Init(void);
void Error_Handler(void);
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */
PROGRAM SLAVE
main.c
#include "main.h"
/* ================= SPI ================= */
SPI_HandleTypeDef hspi1;
/* ================= COMMAND ================= */
#define CMD_GAME_RUN 0x01
#define CMD_GAME_OVER 0x02
#define CMD_JUMP_SOUND 0x03
#define CMD_HIT_SOUND 0x04
/* ================= PROTOTYPE ================= */
void SystemClock_Config(void);
void MX_GPIO_Init(void);
void MX_SPI1_Init(void);
void Send(uint8_t data);
/* ================= MAIN ================= */
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI1_Init();
while (1)
{
Send(CMD_GAME_RUN);
HAL_Delay(500);
Send(CMD_JUMP_SOUND);
HAL_Delay(500);
Send(CMD_GAME_OVER);
HAL_Delay(1000);
}
}
/* ================= SEND SPI ================= */
void Send(uint8_t data)
{
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET); // CS LOW
HAL_SPI_Transmit(&hspi1, &data, 1, 100);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); // CS HIGH
}
/* ================= SPI INIT ================= */
void MX_SPI1_Init(void)
{
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
HAL_SPI_Init(&hspi1);
}
/* GPIO CS */
void MX_GPIO_Init(void)
{
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
}
/* CLOCK (simple safe) */
void SystemClock_Config(void)
{
}
Komentar
Posting Komentar