Files
42_EXT_03_42chips/module02/ex04/main.c
2025-03-09 02:34:11 +01:00

183 lines
5.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h> // https://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html
#include "utils.h"
#include "bitmanip.h"
#include "timer.h"
#include "usart.h"
#include "interrupt.h"
// USART
#define USART_BAUDRATE 115200
// TIMER
#define PERIOD 2000
#define PRESCALE_VALUE 1024 // can be 1, 8, 64, 256, 1024
#define STRLEN_LITERAL(str) (sizeof(str) / sizeof(str[0]) - 1) // -1 to remove the null terminator, only works with string literals, not with pointers
// END MACROS
// FUNCTION PROTOTYPES
void uart_init();
// char uart_rx(void);
void uart_tx(char c);
void uart_printstr(const char* str);
void check_str(char input, volatile char compare_str[], unsigned int length);
void reset_message();
void ask_for_username();
void ask_for_password();
void on_error();
void on_success();
// GLOBAL VARIABLES
typedef enum {
USERNAME,
PASSWORD
} State;
volatile char username[] = "admin";
volatile char password[] = "password";
volatile int input_index = 0;
volatile State state = USERNAME;
volatile int input_match = FALSE;
volatile int username_correct = FALSE;
volatile int password_correct = FALSE;
void uart_init() {
UBRR0H = (unsigned char) (BAUD_PRESCALER(USART_BAUDRATE) >> 8); // 20.11.5 : UBRRnL and UBRRnH USART Baud Rate Registers
UBRR0L = (unsigned char) BAUD_PRESCALER(USART_BAUDRATE);
UCSR0C |= ASYNCHRONOUS | PARITY_DISABLED | STOP_ONE_BIT | DATA_EIGHT_BIT; // 20.11.4 : set Frame Format
UCSR0B |= RECEIVER_ENABLED | TRANSMITTER_ENABLED | INTERRUPT_RECEIVER_ENABLED; // 20.11.3 : enable Receiver and Transmitter, and interrupt on receiver
}
// char uart_rx(void) {
// while (TEST(UCSR0A, RXC0) == 0); // 20.11.2 : do nothing until there are unread data in the receive buffer (UDRn), (RXCn flag in UCSRnA register set to 1 when buffer has data)
// return UDR0; // 20.11.1 : get data in buffer, UDRn USART I/O Data Register (read and write)
// }
void uart_tx(char c) {
while (TEST(UCSR0A, UDRE0) == 0); // 20.11.2 : do nothing until UDRn buffer is empty, (UDREn flag in UCSRnA register set to 1 when buffer empty)
UDR0 = (unsigned char) c; // 20.11.1 : Put data into buffer, UDRn USART I/O Data Register (read and write)
}
void uart_printstr(const char* str) {
while (*str) {
uart_tx(*str);
str++;
}
}
ISR(USART_RX_vect) { // Table 12-7 : we select the code for USART Receive
// char received_char = uart_rx();
char received_char = UDR0; // read received character
if (received_char == '\b' || received_char == 127) { // if backspace is received
if (input_index <= 0) return;
input_index--;
uart_tx('\b'); // Move cursor back
uart_tx(' '); // Erase the character on screen
uart_tx('\b'); // Move cursor back again
} else if (received_char == '\n' || received_char == '\r') { // if enter is received
if (state == USERNAME) {
if (input_index == STRLEN_LITERAL(username) && input_match) {
username_correct = TRUE;
} else {
username_correct = FALSE;
uart_printstr("(error1)");
}
input_match = FALSE;
state = PASSWORD;
input_index = 0;
uart_tx('\r'); // Move cursor to next line
uart_tx('\n');
ask_for_password();
} else if (state == PASSWORD) {
if (!username_correct) {
uart_printstr("(error2)");
return reset_message();
}
if (input_index != STRLEN_LITERAL(password)) {
uart_printstr("(error3)");
return reset_message();
}
if (!input_match) {
uart_printstr("(error4)");
return reset_message();
}
uart_tx('\r'); // Move cursor to next line
uart_tx('\n');
on_success();
}
} else {
if (state == USERNAME) {
check_str(received_char, username, STRLEN_LITERAL(username));
uart_tx(received_char);
}
else if (state == PASSWORD) {
check_str(received_char, password, STRLEN_LITERAL(password));
uart_tx('*');
}
input_index++;
}
}
void check_str(char input, volatile char compare_str[], unsigned int length) {
if (input_index >= length) { // index has not already been incremented, so we need to compare greater or equal
uart_printstr("(error5)");
input_match = FALSE;
return;
}
if (input != compare_str[input_index]) {
uart_printstr("(error6)");
input_match = FALSE;
return;
}
// if we reach this point, the input character matches the compare_str character
if (input_index == 0) {
input_match = TRUE;
return;
}
// if we reach this point, the input character is not the first character of the compare_str
if (input_match == FALSE) {
// if any previous character did not match, we don't need to check the next character
uart_printstr("(error7)");
return;
}
input_match = TRUE;
}
void reset_message() {
input_index = 0;
input_match = FALSE;
username_correct = FALSE;
password_correct = FALSE;
state = USERNAME;
uart_tx('\r'); // Move cursor to next line
uart_tx('\n');
on_error();
ask_for_username();
}
void ask_for_username() {
uart_printstr("Enter your login: \r\n username: ");
}
void ask_for_password() {
uart_printstr(" password: ");
}
void on_error() {
uart_printstr("Bad combinaison username/password\r\n\r\n");
}
void on_success() {
uart_printstr("Hello spectre!\r\nShall we play a game?\r\n");
}
// ask for username and password
// `screen /dev/ttyUSB0 115200`
int main() {
uart_init();
ask_for_username();
SREG |= ENABLE_GLOBAL_INTERRUPT; // 7.3.1 : Status Register, bit 7 : I Global Interrupt Enable
while(1);
}