the3
unknown
plain_text
2 years ago
18 kB
6
Indexable
/* * File: main.c * Author: altug * * Created on May 23, 2023, 4:40 PM */ #include "the3.h" #include "lcd.h" #include <stdio.h> #define teamA 0 #define teamB 1 #define ACTIVE_MODE 0 #define INACTIVE_MODE 1 //special char indexes #define TEAM_A 0 #define TEAM_B 1 #define TEAM_A_SELECTED 2 #define TEAM_B_SELECTED 3 #define FRISBEE_REAL 4 #define FRISBEE_TARGET 5 #define TEAM_A_WITH_FRISBEE 6 #define TEAM_B_WITH_FRISBEE 7 #define SEGMENT_A PORTDbits.RD0 #define SEGMENT_B PORTDbits.RD1 #define SEGMENT_C PORTDbits.RD2 #define SEGMENT_D PORTDbits.RD3 #define SEGMENT_E PORTDbits.RD4 #define SEGMENT_F PORTDbits.RD5 #define SEGMENT_G PORTDbits.RD6 // Common pins (for common cathode display) typedef struct coordinate { byte x; byte y; }coordinate; typedef struct Player{ byte id; byte selected_shape; byte default_shape; byte with_frisbee; byte shape; coordinate prev_coor; coordinate coor; byte team; }Player; typedef struct Frisbee{ coordinate prev_coor; coordinate coor; byte shape; }Frisbee; typedef struct Game{ }Game; byte checkOtherPlayers(coordinate new_coor); byte edgeCheck(coordinate coor); byte hasFrisbee(coordinate coor); byte gameBegins(); void nextStep(); void drawToLCD(Player *player, Frisbee *frisbee); unsigned short x; unsigned short number_of_steps; byte char_ind = 0; byte selected_player = 0; byte rb_flag = 0x00; byte changes; byte counter_timer = 0; byte game_speed = 4; byte blink_operation = 0; byte game_mode = INACTIVE_MODE; byte frisbee_index = 0; byte teamA_points = 0; byte teamB_points = 0; Player players[4]; Frisbee targetFrisbee; Frisbee realFrisbee; byte isEqualCoor(coordinate a, coordinate b){ return a.x == b.x && a.y == b.y; } void score_to_team(byte team){ if(team == TEAM_A) teamA_points++; else if(team == TEAM_B) teamB_points++; } byte roundBegins(){ game_mode = ACTIVE_MODE; frisbee_index = 0; // Turn on Timer0 number_of_steps = compute_frisbee_target_and_route(realFrisbee.coor.x, realFrisbee.coor.y); targetFrisbee.coor.x = frisbee_steps[number_of_steps-1][0]; targetFrisbee.coor.y = frisbee_steps[number_of_steps-1][1]; TMR0 = 3500; T0CONbits.TMR0ON = 1; return game_speed; } byte edgeCheck(coordinate coor){ return (coor.x > 0 && coor.x < 17 && coor.y > 0 && coor.y <5); } byte hasFrisbee(coordinate coor){ return ((realFrisbee.coor.x == coor.x )&& (realFrisbee.coor.y == coor.y ) ); } byte checkOtherPlayers(coordinate new_coor){ for(byte i=0; i<4; i++){ if(i != selected_player){ Player* other_player = &players[i]; if(new_coor.x == other_player->coor.x && new_coor.y == other_player->coor.y) return 0x00; } } return 0x01; } void move_rb(byte index,int dir_x, int dir_y){ Player *player = &players[index]; coordinate candidate_coor = player->coor; candidate_coor.x += dir_x; candidate_coor.y += dir_y; player->prev_coor = player->coor; if (edgeCheck(candidate_coor) ){ if(checkOtherPlayers(candidate_coor)){ if(hasFrisbee(candidate_coor)){ player->shape = player->with_frisbee; } LCDGoto(player->coor.x, player->coor.y); LCDStr(" "); player->coor = candidate_coor; } } drawToLCD(player, NULL); } void move(byte index,int dir_x, int dir_y){ Player *player = &players[index]; coordinate candidate_coor = player->coor; candidate_coor.x += dir_x; candidate_coor.y += dir_y; player->prev_coor = player->coor; if (edgeCheck(candidate_coor) ){ if(checkOtherPlayers(candidate_coor)){ player->coor = candidate_coor; } } } void randomMoves(){ for(int i=0; i<4; i++){ Player* player = &players[i]; if(player->id != selected_player) { unsigned short rnd_short = random_generator(9); switch(rnd_short){ case 1: break; case 2: move(player->id,0,-1); break; case 3: move(player->id,1,-1); break; case 4: move(player->id, 1,0); break; case 5: move(player->id, 1,1); break; case 6: move(player->id, 0,1); break; case 7: move(player->id,-1,1); break; case 8: move(player->id,-1,0); break; } } } } void roundEnd(){ game_mode = INACTIVE_MODE; //LCDGoto(targetFrisbee.coor.x, targetFrisbee.coor.y); //LCDStr(" "); T0CONbits.TMR0ON = 0; // Turn off Timer0 initially } void frisbeeMove(){ byte should_erase = 1; byte is_catched = 0; coordinate old_coor = realFrisbee.coor; for(int i=0; i<4; i++){ Player* temp_player = &players[i]; if(isEqualCoor(temp_player->coor, old_coor)){ should_erase = 0; if(temp_player->id == selected_player){ temp_player->shape = temp_player->selected_shape; } else{ temp_player->shape = temp_player->default_shape; } //drawToLCD(temp_player, NULL); } if(isEqualCoor(temp_player->coor, realFrisbee.coor)){ if(isEqualCoor(targetFrisbee.coor, realFrisbee.coor)){ is_catched = 1; } temp_player->shape = temp_player->with_frisbee; } } if(should_erase){ LCDGoto(old_coor.x, old_coor.y); LCDStr(" "); } if(is_catched == 0){ drawToLCD(NULL, &realFrisbee); } if(isEqualCoor(realFrisbee.coor, targetFrisbee.coor) || is_catched ){ roundEnd(); } } void winner(byte id){ Player *player = &players[id]; score_to_team(player->team); } void drawStep(){ byte draw_frisbee = 1; signed char crossed_id = -1; byte target_reached = isEqualCoor(realFrisbee.coor, targetFrisbee.coor); Player *selected_p = &players[selected_player]; if(isEqualCoor(selected_p->coor, realFrisbee.coor)){ if(target_reached) crossed_id = selected_p->id; selected_p -> shape = selected_p->with_frisbee; draw_frisbee = 0; } if(isEqualCoor(selected_p->coor, realFrisbee.prev_coor)){ selected_p -> shape = selected_p->selected_shape; } LCDGoto(realFrisbee.prev_coor.x, realFrisbee.prev_coor.y ); LCDStr(" "); drawToLCD(selected_p, NULL); for(int i=0; i<4; i++){ if(i != selected_player){ Player *player = &players[i]; if (isEqualCoor(player->prev_coor, player->coor) == 0){ LCDGoto(player->prev_coor.x, player->prev_coor.y); LCDStr(" "); } drawToLCD(player, NULL); if(isEqualCoor(realFrisbee.coor, player->coor)){//random catches if( target_reached) crossed_id = player->id; draw_frisbee = 0; } } } if (target_reached){ if(crossed_id == -1) drawToLCD(NULL, &realFrisbee); else { if(selected_player == crossed_id){ winner(crossed_id); } } roundEnd(); } else if( draw_frisbee ) drawToLCD(NULL, &realFrisbee); } void updateData(){ realFrisbee.prev_coor = realFrisbee.coor; realFrisbee.coor.x = frisbee_steps[frisbee_index][0]; realFrisbee.coor.y = frisbee_steps[frisbee_index][1]; frisbee_index++; randomMoves(); drawStep(); } void __interrupt() ISR() { changes = PORTB; if (INTCONbits.TMR0IF) // Check if Timer0 overflow interrupt flag is set { CONVERT = 1; //rb_flag = 0x00; // Your code to handle the Timer0 overflow interrupt TMR0 = 3500; if(game_mode == ACTIVE_MODE ) { if(blink_operation){ drawToLCD(NULL, &targetFrisbee); blink_operation = 0; } else{ LCDGoto(targetFrisbee.coor.x, targetFrisbee.coor.y); LCDStr(" "); blink_operation = 1; } //target coordinatlarinin lcdye yazilmasi if(++counter_timer == game_speed){ updateData(); counter_timer = 0; } } INTCONbits.TMR0IF = 0; } if (INTCONbits.RBIF) //portb<7:4> { changes ^= 0xFF; if ((changes >>= 4) == 1){ move_rb(selected_player,0,-1); } else if ((changes >>= 1) == 1){ move_rb(selected_player,1,0); } else if ((changes >>= 1 )== 1){ move_rb(selected_player,0,1); } else if ((changes >>= 1 )== 1){ move_rb(selected_player,-1,0); } // Your code to handle the RB0 interrupt PORTA = PORTB; // Clear the RB0 interrupt flag INTCONbits.RBIF = 0; rb_flag++; } else if (INTCONbits.INT0IF){ roundBegins(); INTCONbits.INT0IF = 0; } else if (INTCON3bits.INT1F){ if(PORTBbits.RB1 == 1){ Player* p_player = &players[selected_player]; if(p_player->shape == p_player->with_frisbee) return; if(hasFrisbee(p_player->coor)) p_player->shape = p_player->with_frisbee; else p_player->shape = p_player->default_shape; selected_player = (++selected_player) % 4; Player *a_player = &players[selected_player]; a_player->shape = a_player->selected_shape; drawToLCD(p_player, NULL); drawToLCD(a_player, NULL); } INTCON3bits.INT1F = 0; } } void initializePlayers(Player *players){ players[0].id = 0; players[0].shape = TEAM_A_SELECTED; players[0].selected_shape = TEAM_A_SELECTED; players[0].default_shape = TEAM_A; players[0].with_frisbee = TEAM_A_WITH_FRISBEE; players[0].coor.x = 3; players[0].coor.y = 2; players[0].team = teamA; players[1].id = 1; players[1].shape = TEAM_A; players[1].selected_shape = TEAM_A_SELECTED; players[1].default_shape = TEAM_A; players[1].with_frisbee = TEAM_A_WITH_FRISBEE; players[1].coor.x = 3; players[1].coor.y = 3; players[1].team = teamA; players[2].id = 2; players[2].shape = TEAM_B; players[2].selected_shape = TEAM_B_SELECTED; players[2].default_shape = TEAM_B; players[2].with_frisbee = TEAM_B_WITH_FRISBEE; players[2].coor.x = 14; players[2].coor.y = 2; players[2].team = teamB; players[3].id = 3; players[3].shape = TEAM_B; players[3].selected_shape = TEAM_B_SELECTED; players[3].default_shape = TEAM_B; players[3].with_frisbee = TEAM_B_WITH_FRISBEE; players[3].coor.x = 14; players[3].coor.y = 3; players[3].team = teamB; return; } void initializeFrisbee(Frisbee *real, Frisbee *target){ real->coor.x = 9; real->coor.y = 2; real->shape = FRISBEE_REAL; target->coor.x = 1; target->coor.y = 1; target->shape = FRISBEE_TARGET; } void initSpecialCharacters(){ LCDAddSpecialCharacter(TEAM_A, &teamA_player); LCDAddSpecialCharacter(TEAM_B, &teamB_player); LCDAddSpecialCharacter(TEAM_A_SELECTED, &selected_teamA_player); LCDAddSpecialCharacter(TEAM_B_SELECTED, &selected_teamB_player); LCDAddSpecialCharacter(FRISBEE_REAL, &frisbee); LCDAddSpecialCharacter(FRISBEE_TARGET, &frisbee_target); LCDAddSpecialCharacter(TEAM_A_WITH_FRISBEE, &selected_teamA_player_with_frisbee); LCDAddSpecialCharacter(TEAM_B_WITH_FRISBEE, &selected_teamB_player_with_frisbee); } // either draws player or frisbee to lcd void drawToLCD(Player *player, Frisbee *frisbee){ if( player ){ LCDGoto(player->coor.x,player->coor.y); LCDDat(player->shape); } else if (frisbee){ LCDGoto(frisbee->coor.x, frisbee->coor.y); LCDDat(frisbee->shape); } return; } void InitInterrupts(){ byte x = PORTB; PORTB = 0xFF; TRISB = 0xFF; INTCONbits.GIE = 1; INTCONbits.PEIE = 1; //PORTB <7:4> ADCON1 = 0x0F; x = PORTB; INTCONbits.RBIF = 0; //clear flag PORTB = 0x00; INTCONbits.RBIE = 1; //enable //RB0 INTCONbits.INT0IF = 0; //clear flag INTCONbits.INT0E = 1; //enable INTCON2bits.INTEDG0 = 1; //rising edge INTCON2bits.RBPU = 1; //RB1 INTCON3bits.INT1F = 0; //clear flag INTCON3bits.INT1E = 1; //enable INTCON2bits.INTEDG1 = 0; //rising edge T0CONbits.TMR0ON = 0; // Turn off Timer0 initially T0CONbits.T08BIT = 0; // Configure Timer0 as a 16-bit timer T0CONbits.T0CS = 0; // Select internal instruction cycle clock (Fosc/4) as the clock source T0CONbits.PSA = 0; // Assign prescaler to Timer0 T0CONbits.T0PS2 = 0; // Set the prescaler value to 1:64 T0CONbits.T0PS1 = 1; T0CONbits.T0PS0 = 1; TMR1ON = 1; // Enable Timer1 T1CONbits.TMR1CS = 0; // Internal clock (Fosc/4) T1CONbits.T1CKPS = 0b00; // 1:8 prescaler T1CONbits.RD16 = 1; TMR1 = 0x00; // Clear Timer1 high byte // Clear Timer1 low byte // Calculate the Timer0 initial value based on desired time period // For a 400ms interrupt with a 1:64 prescaler and 10 MHz clock frequency, the initial value is: TMR0 = 6800; // Enable Timer0 overflow interrupt INTCONbits.TMR0IE = 1; // Enable Timer0 overflow interrupt // Configure and enable global interrupts // Start Timer0 ADCON1bits.PCFG3 = 1; // RA0 = Analog, RA1=1 Analog, RA2 = Analog ADCON1bits.PCFG2 = 1; ADCON1bits.PCFG1 = 0; ADCON1bits.PCFG0 = 0; ADCON1bits.VCFG0 = 0; // Vref+=5.0, Vref=0 ADCON1bits.VCFG1 = 0; TRISAbits.RA0 = 1; TRISAbits.RA1 = 1; TRISAbits.RA2 = 0; // For 40MHZ -> Tosc = 1/40 us // Tad options (2xTosc, 4xTosc, 8xTosc, 16xTosc, 32xTosc, 64xTosc) // min Tad 0.7 us - max Tad 25 us (Keep as short as possible) // The closest one to min Tad (32xTosc) hence Tad = 32xTosc = 0.8 us (ADCS2:ADCS0=010) // Acquisition time options (0xTad, 2xTad, 4xTad, 6xTad, 8xTad, 12xTad, 16xTad, 20xTad) // Min acquisition time = 2.4 us (the closest acquisition time we can set 4xTad = 3.2us) (ACQT2:ACQT0=010) ADCON2bits.ADCS2 = 0; // Tad (32xTOSC) -> 0.8us ADCON2bits.ADCS1 = 1; ADCON2bits.ADCS0 = 0; ADCON2bits.ACQT2 = 0; // Acquisition time (4xTad) = 3.2 us ADCON2bits.ACQT1 = 1; ADCON2bits.ACQT0 = 0; ADCON2bits.ADFM = 1; // Right justified... ADCON0bits.ADON = 1; // ADC module is enabled.... } unsigned short readADCChannel(unsigned char channel) { // 0b 0101 -> 5th chanel ADCON0bits.CHS0 = channel & 0x1; // Select channel.. ADCON0bits.CHS1 = (channel >> 1) & 0x1; ADCON0bits.CHS2 = (channel >> 2) & 0x1; ADCON0bits.CHS3 = (channel >> 3) & 0x1; ADCON0bits.GODONE = 1; //Start convertion while(ADCON0bits.GODONE == 1); //Wait the conversion to finish PIR1bits.ADIF = 0; // Clear interrupt flag... return (unsigned short)((ADRESH << 8)+ADRESL); } unsigned short setGameSpeed(unsigned short adcVal){ if (adcVal > 0 && adcVal < 256){ return 4; } if (adcVal > 255 && adcVal < 512){ return 8; } if (adcVal > 511 && adcVal < 768){ return 12; } if (adcVal > 767 && adcVal < 1024){ return 16; } } /* void displayDigit(unsigned char digit, unsigned char display) { // Segment patterns for each digit (common cathode) const unsigned char digitPatterns[10] = { 0b00111111, // 0 0b00000110, // 1 0b01011011, // 2 0b01001111, // 3 0b01100110, // 4 0b01101101, // 5 0b01111101, // 6 0b00000111, // 7 0b01111111, // 8 0b01101111 // 9 }; // Activate the corresponding segments for the given digit SEGMENT_A = (digitPatterns[digit] & 0x01); SEGMENT_B = (digitPatterns[digit] & 0x02) >> 1; SEGMENT_C = (digitPatterns[digit] & 0x04) >> 2; SEGMENT_D = (digitPatterns[digit] & 0x08) >> 3; SEGMENT_E = (digitPatterns[digit] & 0x10) >> 4; SEGMENT_F = (digitPatterns[digit] & 0x20) >> 5; SEGMENT_G = (digitPatterns[digit] & 0x40) >> 6; // Activate the selected display DIGIT_1 = (display == 1) ? 1 : 0; DIGIT_2 = (display == 2) ? 1 : 0; DIGIT_3 = (display == 3) ? 1 : 0; DIGIT_4 = (display == 4) ? 1 : 0; }*/ void main(void) { TRISD = 0x00; initializePlayers(players); initializeFrisbee(&realFrisbee, &targetFrisbee); InitLCD(); InitInterrupts(); initSpecialCharacters(); drawToLCD(&players[0], NULL ); drawToLCD(&players[1], NULL ); drawToLCD(&players[2], NULL ); drawToLCD(&players[3], NULL ); drawToLCD(NULL, &realFrisbee ); char values[10] = {0}; unsigned short convertion = 0; const unsigned char digitPatterns[10] = { 0b00111111, // 0 0b00000110, // 1 0b01011011, // 2 0b01001111, // 3 0b01100110, // 4 0b01101101, // 5 0b01111101, // 6 0b00000111, // 7 0b01111111, // 8 0b01101111 // 9 }; while (1){ if(CONVERT == 1) { convertion = readADCChannel(0); game_speed = setGameSpeed(convertion); CONVERT = 0; } PORTBbits.RB0 = 1; PORTBbits.RB1 = 0; PORTBbits.RB2 = 1; PORTBbits.RB3 = 1; PORTD = 0x66; __delay_ms(1000); //add delay of one second } return; }
Editor is loading...