From b05b9f0298e147caf0c0c18b6ad11a941a238243 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Fri, 7 Mar 2025 13:00:42 +0100 Subject: [PATCH] mod02 ex03 init --- module02/ex03/Makefile | 1 + module02/ex03/main.c | 151 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 module02/ex03/Makefile create mode 100644 module02/ex03/main.c diff --git a/module02/ex03/Makefile b/module02/ex03/Makefile new file mode 100644 index 0000000..2e40cba --- /dev/null +++ b/module02/ex03/Makefile @@ -0,0 +1 @@ +include ../../Makefile \ No newline at end of file diff --git a/module02/ex03/main.c b/module02/ex03/main.c new file mode 100644 index 0000000..2c780c4 --- /dev/null +++ b/module02/ex03/main.c @@ -0,0 +1,151 @@ +#include +#include +#include + +// mathematics +#define DIV_ROUND_CLOSEST(n, d) ((((n) < 0) == ((d) < 0)) ? (((n) + (d)/2)/(d)) : (((n) - (d)/2)/(d))) // https://stackoverflow.com/a/18067292 + +// stringify +#define STRINGIFY_HELPER(x) #x +#define STRINGIFY(x) STRINGIFY_HELPER(x) + +// concatenate +#define CONCAT_HELPER(x, y) x ## y +#define CONCAT(x, y) CONCAT_HELPER(x, y) + +// get argument +#define ARG_1(v1, v2) v1 +#define ARG_2(v1, v2) v2 +#define GET_PORT(args) ARG_1 args +#define GET_BIT(args) ARG_2 args +// // version with "LED1 B, D1" without parenthesis +// #define ARG_1(v1, ...) v1 +// #define ARG_2(v1, v2, ...) v2 +// #define GET_PORT(...) ARG_1(__VA_ARGS__) +// #define GET_BIT(...) ARG_2(__VA_ARGS__) + +// actions on registers +#define SET(register, bit) register |= 1 << bit +#define CLEAR(register, bit) register &= ~(1 << bit) +#define TEST(register, bit) (register & 1 << bit) +#define TOGGLE(register, bit) register ^= 1 << bit + +// actions on elements +#define SET_ELEM(elem) SET(CONCAT(PORT, GET_PORT(elem)), GET_BIT(elem)) +// #define SET_ELEM(...) SET(CONCAT(PORT, GET_PORT(__VA_ARGS__)), GET_BIT(__VA_ARGS__)) // version for "LED1 B, D1" without parenthesis +#define CLEAR_ELEM(elem) CLEAR(CONCAT(PORT, GET_PORT(elem)), GET_BIT(elem)) +#define TEST_ELEM(elem) TEST(CONCAT(PORT, GET_PORT(elem)), GET_BIT(elem)) +#define TOGGLE_ELEM(elem) TOGGLE(CONCAT(PORT, GET_PORT(elem)), GET_BIT(elem)) +#define MODE_OUTPUT(elem) SET(CONCAT(DDR, GET_PORT(elem)), GET_BIT(elem)) +#define MODE_INPUT(elem) CLEAR(CONCAT(DDR, GET_PORT(elem)), GET_BIT(elem)) +#define TOGGLE_PIN(elem) SET(CONCAT(PIN, GET_PORT(elem)), GET_BIT(elem)) +#define TEST_PIN(elem) (TEST(CONCAT(PIN, GET_PORT(elem)), GET_BIT(elem))) +#define IS_PIN_SET(elem) (TEST_PIN(elem) == 0) +#define IS_PIN_CLEAR(elem) (TEST_PIN(elem) == 1) + +// bits +#define D1 0 +#define D2 1 +#define D3 2 +#define D4 4 +#define SW1 2 +#define SW2 4 + +// elements (port, bit) +// #define LED1 B, D1 +#define LED1 (B, D1) +#define LED2 (B, D2) +#define LED3 (B, D3) +#define LED4 (B, D4) +#define BUTTON1 (D, SW1) +#define BUTTON2 (D, SW2) + +// USART +// Table 20-1 : Baud Rate Calculation +#define USART_BAUDRATE 115200 +#define BAUD_PRESCALER (DIV_ROUND_CLOSEST(F_CPU, (16 * USART_BAUDRATE)) - 1) +// Table 20-8 : Mode Selection (USART Mode SELect) +#define ASYNCHRONOUS (0<> 8); // 20.11.5 : UBRRnL and UBRRnH – USART Baud Rate Registers + UBRR0L = (unsigned char) BAUD_PRESCALER; + + UCSR0C |= ASYNCHRONOUS | PARITY_DISABLED | STOP_ONE_BIT | DATA_EIGHT_BIT; // 20.11.4 : set Frame Format + + UCSR0B |= RECEIVER_ENABLED | TRANSMITTER_ENABLED; // 20.11.3 : enable Receiver and/or Transmitter +} + +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) +} + +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) +} + +// send back caracters received on serial port +// `screen /dev/ttyUSB0 115200` +int main() { + uart_init(); + + TCCR1A |= CTC_TOP_OCR1A_IN_TCCR1A; // Table 16-4 : set timer in CTC (Clear Time on Compare) mode + TCCR1B |= CTC_TOP_OCR1A_IN_TCCR1B; + + OCR1A = TIME_MS(PERIOD); // Table 16-4 : set CTC compare value on channel A, the counter is cleared to zero when the counter value (TCNT1) matches the OCR1A register + + TCCR1B |= (PRESCALE_SET(PRESCALE_VALUE)); // 16.4 : set timer according to prescale value, in register TCCR1B, table 16-5 : prescale sets + + char received_char; + while(1) { + received_char = uart_rx(); + uart_tx(received_char); + } +}