Untitled
unknown
plain_text
3 years ago
9.3 kB
5
Indexable
#ifndef F_CPU
#define F_CPU 16000000UL // Set 16 MHz clock speed
#endif
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <Arduino.h>
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE ((((F_CPU / 16) + (USART_BAUDRATE / 2)) / (USART_BAUDRATE)) - 1)
#define N 8
#define MAX_SHOT 16
#define MAX_SHIP 5
// struct Ship {
// int row;
// int col;
// int drow;
// int dcol;
// void setup(int row, int col, int drow, int dcol) {
// this->row = row;
// this->col = col;
// this->drow = drow;
// this->dcol = dcol;
// }
// };
struct Button
{
char c;
int p;
unsigned int state = 0;
void setup(char c, int p)
{
this->c = c;
this->p = p;
state = 0;
}
bool debounce()
{
switch (c)
{
case 'c':
state = (state << 1) | (!(PINC & (1 << p))) | 0xfe00;
break;
default:
break;
}
return (state == 0xff00);
}
};
void setupGame();
void setupPort();
void setupTimer();
void setupInterrupt();
void setupButton();
void setupUart();
int isGameFinish();
void turnOnSevenSegment();
void updateCoordinate(int sign);
void toggleXYMode();
void updateShipSunkedCount();
void replayGame();
int makeCoordinateInBound(int x);
int inMap(int row, int col);
int controlLedB[] = {0b000000, 0b111001, 0b100100, 0b110000, 0b011001, 0b010010, 0b000010, 0b111000, 0b000000, 0b010000, 0b111111};
int controlLedC[] = {1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1};
volatile int dRow[] = {0, 1};
volatile int dCol[] = {1, 0};
volatile int ledPointer = 0;
volatile int blinkLed = 0;
volatile int blinkLedCounter = 0;
volatile int softwareCounter = 0;
volatile int isSevenSegmentOn = 1;
volatile int isBtnShotActive = 1;
volatile int xCor = 1;
volatile int yCor = 1;
volatile int xyMode = 1;
volatile int gameMap[N][N] = {{1, 0, 1, 0, 0, 0, 0, 0},
{1, 0, 1, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{1, 0, 1, 0, 0, 0, 0, 0},
{1, 0, 1, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0},
{1, 0, 0, 0, 0, 0, 0, 0},
{1, 0, 0, 0, 0, 0, 0, 0}};
// volatile int gameMap[N][N];
volatile int shotMap[N][N];
volatile int receivedByteCount = 0;
volatile int shipSunkedCount = 0;
volatile int hitCount = 0;
volatile int shotCount = 0;
Button btnUp;
Button btnDown;
Button btnXY;
Button btnReplay;
int main(void)
{
// Setup software
setupGame();
// Setup all hardware
setupPort();
setupTimer();
setupButton();
setupUart();
setupInterrupt();
while (1)
{
if (TIFR1 & (1 << OCF1A))
{
isBtnShotActive = 1;
}
if (btnUp.debounce())
{
// Move up
updateCoordinate(1);
continue;
}
if (btnDown.debounce())
{
// Move down
updateCoordinate(-1);
continue;
}
if (btnXY.debounce())
{
// Toggle xy
toggleXYMode();
continue;
}
if (btnReplay.debounce())
{
setupGame();
continue;
}
}
}
void setupGame()
{
// Reset the data of the game
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
shotMap[i][j] = 0;
}
}
receivedByteCount = shipSunkedCount = hitCount = shotCount = 0;
}
void setupPort()
{
// Port for 7-segment LED and button
DDRB = 0x3F;
DDRC = 0x21;
// Port for external interrupt button
DDRD &= ~(1 << 2);
DDRD |= (1 << 1);
for (int i = 3; i <= 7; i++)
{
DDRD |= (1 << i);
}
}
void setupTimer()
{
// Timer 0 for control 7 segment
TCCR0A |= (1 << WGM01);
TCCR0B |= ((1 << CS01) | (1 << CS00));
OCR0A = 255;
// Timer 1 for stoping
TCCR1B |= (1 << WGM12);
TCCR1B |= (1 << CS12);
OCR1A = 31249;
}
void setupInterrupt()
{
// Interrupt for timer 1
TIMSK0 |= (1 << OCIE0A);
// Interrupt for rx
UCSR0B |= (1 << RXCIE0);
// Interrupt for button
EICRA |= (1 << ISC01);
EIMSK |= (1 << INT0);
sei();
}
void setupButton()
{
// Setup the button variable for implement the debounce functionality
btnUp.setup('c', 1);
btnDown.setup('c', 2);
btnXY.setup('c', 3);
btnReplay.setup('c', 4);
}
void setupUart()
{
UBRR0H = (BAUD_PRESCALE >> 8);
UBRR0L = (BAUD_PRESCALE);
UCSR0C = ((1 << UCSZ00) | (1 << UCSZ01));
UCSR0B |= ((1 << RXEN0) | (1 << TXEN0));
}
int isGameFinish()
{
return shipSunkedCount >= MAX_SHIP || shotCount >= MAX_SHOT;
}
void turnOnSevenSegment() {
// Turn on the port to display exactly 1 digit
PORTD |= (1 << (ledPointer + 3));
switch (ledPointer)
{
case 0:
// Display the no of ships sunk
PORTB = controlLedB[shotCount % 10];
PORTC = controlLedC[shotCount % 10];
break;
case 1:
// Display the no of hits
PORTB = controlLedB[shotCount / 10];
PORTC = controlLedC[shotCount / 10];
break;
case 2:
// Display the no of shots (digit 1)
PORTB = controlLedB[hitCount];
PORTC = controlLedC[hitCount];
break;
case 3:
// Display the no of shots (digit 0)
PORTB = controlLedB[shipSunkedCount];
PORTC = controlLedC[shipSunkedCount];
break;
case 4:
// Display xy coordinate
PORTB = controlLedB[(!xyMode) ? xCor : yCor];
PORTC = controlLedC[(!xyMode) ? xCor : yCor];
break;
default:
// Reset to turn off
PORTB = controlLedB[0];
PORTC = controlLedC[0];
}
// Move to the next digit
ledPointer = (ledPointer + 1) % 5;
}
void updateCoordinate(int sign)
{
if (isGameFinish())
{
return;
}
// Update xy
xCor += (!xyMode) ? sign : 0;
yCor += (xyMode) ? sign : 0;
// Avoid the coordiate move out the range 1 - 8
xCor = makeCoordinateInBound(xCor);
yCor = makeCoordinateInBound(yCor);
}
void toggleXYMode()
{
if (isGameFinish())
{
return;
}
xyMode = 1 - xyMode;
}
void updateShipSunkedCount()
{
shipSunkedCount = 0;
for (int row = 0; row < N; row++)
{
for (int col = 0; col < N; col++)
{
for (int i = 0; i < 2; i++)
{
int nextRow = row + dRow[i], nextCol = col + dCol[i];
if (shotMap[row][col] && shotMap[nextRow][nextCol])
{
shipSunkedCount++;
}
}
}
}
}
void replayGame()
{
}
int makeCoordinateInBound(int x)
{
x = (x > 8) ? 1 : x;
x = (x < 1) ? 8 : x;
return x;
}
int inMap(int row, int col)
{
return row >= 0 && row < N && col >= 0 && col < N;
}
ISR(TIMER0_COMPA_vect)
{
if (isGameFinish())
{
// When the game is finished
for (int i = 3; i <= 7; i++)
{
PORTD &= ~(1 << i);
}
if (isSevenSegmentOn) {
turnOnSevenSegment();
}
softwareCounter++;
if (softwareCounter == 800) {
isSevenSegmentOn = 1 - isSevenSegmentOn;
softwareCounter = 0;
}
return;
}
// Turn off the port for display digit
for (int i = 3; i <= 7; i++)
{
PORTD &= ~(1 << i);
}
turnOnSevenSegment();
}
// ISR(USART_RX_vect)
// {
// char receivedByte;
// receivedByte = UDR0;
// if (receivedByte == '0' || receivedByte == '1')
// {
// int row = receivedByteCount / N, col = receivedByteCount % N;
// gameMap[row][col] = receivedByte - '0';
// receivedByteCount = (receivedByteCount + 1) % (N * N);
// }
// }
ISR(INT0_vect)
{
sei();
if (!isBtnShotActive)
{
return;
}
if (isGameFinish())
{
return;
}
TIFR1 |= (1 << OCF1A);
isBtnShotActive = 0;
// The target shot
volatile int row = yCor - 1, col = xCor - 1;
xCor = yCor = xyMode = 1;
// Increase shot count
shotCount++;
// Do nothing if the cell is already shot or it has no ship
if (shotMap[row][col] || !gameMap[row][col])
{
return;
}
// Increase the hitted shot
hitCount++;
shotMap[row][col] = 1;
updateShipSunkedCount();
for (int j = 0; j < 3; j++)
{
Serial.println("Turn");
// PORTC |= (1 << 5);
// _delay_ms(1000);
// PORTC &= ~(1 << 5);
// _delay_ms(1000);
PORTD |= (1 << 1);
_delay_ms(1000);
PORTD &= ~(1 << 1);
_delay_ms(1000);
}
}Editor is loading...