Untitled
unknown
plain_text
3 years ago
9.3 kB
3
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...