#include #include #include // 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); }