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

204 lines
5.3 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
// END MACROS
// FUNCTION PROTOTYPES
void uart_init();
// char uart_rx(void);
void uart_tx(char c);
void uart_printstr(const char* str);
void remove_last_character();
void fill_str(char input);
int compare_str(volatile char *input_str, volatile char *base_str);
int strlength(volatile char *str);
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 char username_input[100] = {0};
volatile char password_input[100] = {0};
volatile int input_index = 0;
volatile State state = USERNAME;
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;
remove_last_character();
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 (compare_str(username_input, username)) {
username_correct = TRUE;
} else {
username_correct = FALSE;
// uart_printstr("(error1)");
}
state = PASSWORD;
input_index = 0;
uart_tx('\r');
uart_tx('\n');
ask_for_password();
} else if (state == PASSWORD) {
if (!username_correct) {
// uart_printstr("(error2)");
return reset_message();
}
if (!compare_str(password_input, password)) {
// uart_printstr("(error3)");
return reset_message();
}
uart_tx('\r');
uart_tx('\n');
on_success();
}
} else {
fill_str(received_char);
if (state == USERNAME) {
uart_tx(received_char);
}
else if (state == PASSWORD) {
uart_tx('*');
}
input_index++;
}
}
void fill_str(char input) {
if (input_index >= 100) {
// uart_printstr("(error4)");
return;
}
if (state == USERNAME) {
username_input[input_index] = input;
} else if (state == PASSWORD) {
password_input[input_index] = input;
}
}
void remove_last_character() {
if (state == USERNAME) {
username_input[input_index] = 0;
} else if (state == PASSWORD) {
password_input[input_index] = 0;
}
}
int compare_str(volatile char *input_str, volatile char *base_str) {
int base_length = strlength(base_str);
int input_length = strlength(input_str);
if (base_length != input_length) {
// uart_printstr("(error5)");
return FALSE;
}
for(int i = 0; i < base_length; i++) {
if (input_str[i] != base_str[i]) {
// uart_printstr("(error6)");
return FALSE;
}
}
return TRUE;
}
int strlength(volatile char *str) {
int length = 0;
while (*str) {
length++;
str++;
}
return length;
}
void reset_message() {
for(int i = 0; i < 100; i++) {
username_input[i] = 0;
password_input[i] = 0;
}
input_index = 0;
username_correct = FALSE;
password_correct = FALSE;
state = USERNAME;
uart_tx('\r');
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);
}