Untitled
unknown
plain_text
2 years ago
9.1 kB
14
Indexable
#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;
}
}
Editor is loading...