Untitled

mail@pastecode.io avatarunknown
plain_text
a month ago
9.1 kB
4
Indexable
Never
#include <float.h>

// PROGRAMMING TASK 1
#define LED_PIN 7 // Represents PB7 (Arduino pin 13)
#define MAXFN 13 // Maximum factorial number that could be correctly calculated and displayed
#define MAXE 87178289000 // Maximum double value that can be represented

static FILE uart00;
static unsigned int persistentValueInMemory = 0;
char convertedString[20];
char unitCodeAndTitle[] = "SEE222: Problem Solving Task - Part A";
char programName[] = "Custom Arduino Calculator";
char studentName[] = "RODRIGO LADESLAU DA CRUZ";
char studentID[] = "222165538";
char selectedCommand = 'P'; // Assigning a random character to initialize the variable that is not on the list of choices

void setup() {
  int i = 0;
  USART0_init();
  // Set pins A0 to A15 and 30 to 37 as inputs with pull-up resistors
  for(i = 0; i < 8; i++){
    pinModeInputPullup(i, 'F'); // A0 to A7
    pinModeInputPullup(i, 'K'); // A8 to A15
    pinModeInputPullup(i, 'C'); // 30 to 37
  }
  // Set pins 40 to 47 as inputs with pull-up resistors
  for(i = 0; i < 2; i++){
    pinModeInputPullup(i, 'G'); // 40 to 41
  }
  for(i = 7; i >= 2; i--){
    pinModeInputPullup(i, 'L'); // 42 to 47
  }
  // Set pin 13 as output
  DDRB |= (1 << LED_PIN);

  // Display initialization texts
  printf("%s\n", unitCodeAndTitle);
  printf("%s\n", programName);
  printf("%s\n", studentName);
  printf("%s\n", studentID);
  printf("%e\n", MAXE);
}

void loop() {
  unsigned char value1 = 0, value2 = 0, value3 = 0, value4 = 0, value5 = 0;
  // Turn on LED on PIN 13
  PORTB |= (1 << LED_PIN); // Turn on LED on pin 13 (PB7)

  // Resquet command from external user via serial PORT
  printf("Select one option:\n A \n ! \n E \n M \n R \n C \n");
  scanf("%c", &selectedCommand);
  while((getchar()) != '\n'); // Read and discard newline. The getchar() function will read and discard characters until it encounters a newline ('\n'), effectively clearing the input buffer.

  // Turn off LED on PIN 13
  PORTB &= ~(1 << LED_PIN); // Turn off LED on pin 13 (PB7)
  printf("You selected %c \n", selectedCommand);
  _delay_ms(500);
  switch(selectedCommand){
    case 'A':
      printf("Enter Value 1:\n");
      while((getchar()) != '\n'); //  Wait until user presses Enter and clear the buffer
      printf("%d\n", PINF); // Read Value1 from pins [A7 A6 … A1 A0] and show it in decimal on the screen
      value1 = PINF;

      printf("Enter Value 2:\n");
      while((getchar()) != '\n'); //  Wait until user presses Enter and clear the buffer
      printf("%d\n", PINK); // Read Value1 from pins [A15 A14 … A9 A8] and show it in decimal on the screen
      value2 = PINK;

      printf("Enter Value 3:\n"); // 
      while((getchar()) != '\n'); // Wait until user presses Enter and clear the buffer
      printf("%d\n", reverseBits(PINC)); // We need to be careful with this one because PC7 is the LSB in the presented logic, so we will reverse
      value3 = reverseBits(PINC);

      printf("Enter Value 4:\n"); //
      while((getchar()) != '\n'); //  Wait until user presses Enter and clear the buffer
      value4 = ((PING & (1 << PG1)) >> PG1) |
                ((PING & (1 << PG0)) >> PG0 << 1) |
                ((PINL & (1 << PL7)) >> PL7 << 2) |
                ((PINL & (1 << PL6)) >> PL6 << 3) |
                ((PINL & (1 << PL5)) >> PL5 << 4) |
                ((PINL & (1 << PL4)) >> PL4 << 5) |
                ((PINL & (1 << PL3)) >> PL3 << 6) |
                ((PINL & (1 << PL2)) >> PL2 << 7); // We first check the value in the register with the & operator. Then we shift it back to the position 0 and shift it again to the desired position. 
      printf("%d\n", value4); // Due to the complexity, it was easier to compose the whole register corresponding operations

      do {
        printf("Enter Value 5 (between 0 and 255):\n");
        scanf("%d", &value5);
        while((getchar()) != '\n'); // Wait until user presses Enter and clear the buffer
      } while (value5 < 0 || value5 >= 256);
      printf("%d\n", value5); // Read Value5 from keyboard, show it on the screen
      dtostrf((value1 + value2 + value3 + value4 + value5)/5.0, 6, 2, convertedString);
      printf("Average: %s\n", convertedString); // Show the outcome of the average
      break;
    case '!':
      do {
        printf("Enter Value 5 (between 0 and 255):\n");
        scanf("%d", &value5);
        while((getchar()) != '\n'); // Wait until user presses Enter and clear the buffer
      } while (value5 < 0 || value5 >= 256);
      if (value5 > MAXFN){
        printf("infinity\n");
      } else {
        dtostrf(factorial(value5), 12, 1, convertedString);
        printf("Factorial: %s\n", convertedString); // Show the the outcome of factorial
      // 13 was the maximum factorial that could be correctly represented
      } 
      break;
    case 'E':
      do {
        printf("Enter Value 5 (between 0 and 255):\n");
        scanf("%d", &value5);
        while((getchar()) != '\n'); // Wait until user presses Enter and clear the buffer
      } while (value5 < 0 || value5 >= 256);
      printf("%d\n", value5); // Read Value5 from keyboard, show it on the screen
      printf("Enter Value 2:\n");
      while((getchar()) != '\n'); //  Wait until user presses Enter and clear the buffer
      printf("%d\n", PINK); // Read Value1 from pins [A15 A14 … A9 A8] and show it in decimal on the screen
      value2 = PINK;
      if (isExponentiable(value5, value2)){
        dtostrf(power(value5, value2), 12, 1, convertedString);
        printf("Outcome of exponentiation: %s\n", convertedString); // Show the the outcome of exponentiation
      } else{
        printf("infinity\n");
      }
      break;
    case 'M':
      do {
        printf("Enter Value 5 (between 0 and 255):\n");
        scanf("%d", &value5);
        while((getchar()) != '\n'); // Wait until user presses Enter and clear the buffer
      } while (value5 < 0 || value5 >= 256);

      persistentValueInMemory += value5;

      printf("New value stored in memory: %u\n", persistentValueInMemory); // Show the the outcome of exponentiation
      break;
    case 'R':
      printf("Current value stored in memory: %u\n", persistentValueInMemory); // Show the the outcome of exponentiation
      break;
    case 'C':
      persistentValueInMemory = 0;
      printf("Current value stored in memory: %u\n", persistentValueInMemory); // Show the the outcome of exponentiation
      break;
    default:
      // Handle unknown commands here:
      printf("Unknown command %c\n", selectedCommand);
      break;
  }
}

void USART0_init(void){
  // Initialize USART0 peripheral
  UCSR0A = 0;
  UCSR0B = (1 << TXEN0) | (1 << RXEN0);
  UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
  UBRR0 = 103;
  fdev_setup_stream(&uart00, TX, RX, _FDEV_SETUP_RW);
  stdin = stdout = &uart00;
}

static int RX(FILE *stream) {
  // Wait until data is received and is ready to be read from UDR0
  while ((UCSR0A & (1 << RXC0)) == 0);

  // When flag is set, read data from USART0 register and return it
  return UDR0;
}

static int TX(char TXData, FILE *stream) {
  // Wait until the transmit buffer is empty
  while ((UCSR0A & (1 << UDRE0)) == 0);

  // Write the byte to the transmit buffer
  UDR0 = TXData;
  return 0;
}

unsigned char reverseBits(unsigned char registerToReverse) {
    int numOfBits = 8;
    unsigned char reverseNum = 0;
    int i;

    for (i = 0; i < numOfBits; i++) {
        if((registerToReverse & (1 << i)))
           reverseNum |= 1 << ((numOfBits - 1) - i);
    }

    return reverseNum;
}

double factorial(int n) {
    double fact = 1;
    for(int i = 2; i <= n; i++) {
        fact *= i;
    }
    return fact;
}

bool isExponentiable(unsigned char base, unsigned char exponent) {
  if (base == 0) {
    return true; // 0 raised to any power is 0
  }
  if (exponent == 0) {
    return true; // any number raised to 0 is 1
  }
  
  float logMax = log(MAXE);
  float logMin = log(-MAXE);

  // Check for overflow
  if (exponent * log(fabs(base)) > logMax) {
    return false;
  }

  // Check for underflow
  if (exponent * log(fabs(base)) < logMin) {
    return false;
  }

  return true;
}

double power(unsigned char base, unsigned char exponent) {
    double result = 1;
    for(int i = 0; i < exponent; i++) {
        result *= base;
    }
    return result;
}

void pinModeInputPullup(int pin, char port){
  switch(port){
    case 'F':
      DDRF &= ~(1 << pin);
      PORTF |= (1 << pin);
      break;
    case 'K':
      DDRK &= ~(1 << pin);
      PORTK |= (1 << pin);
      break;
    case 'C':
      DDRC &= ~(1 << pin);
      PORTC |= (1 << pin);
      break;
    case 'L':
      DDRL &= ~(1 << pin);
      PORTL |= (1 << pin);
      break;
    case 'G':
      DDRG &= ~(1 << pin);
      PORTG |= (1 << pin);
      break;
    default:
      // Handle unknown ports here:
      printf("Unknown port: %c\n", port);
      break;
  }
}