@@ -13,11 +13,37 @@
// 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
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
@@ -35,22 +61,120 @@ void uart_tx(char c) {
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 ; // R ead received character
if ( received_char = = ' \b ' | | received_char = = 127 ) { // I f backspace is received
char received_char = UDR0 ; // r ead received character
if ( received_char = = ' \b ' | | received_char = = 127 ) { // i f 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 {
uart_tx ( SWITCH_CASE ( received_char ) ) ; // Toggle case and send back
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 \n Shall 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