add rush 00

This commit is contained in:
hugogogo
2025-03-15 16:39:29 +01:00
parent 1d5e8d4ee7
commit 70db631c93
15 changed files with 598 additions and 1 deletions

View File

@@ -89,4 +89,5 @@ avrdude done. Thank you.
## screen
- (optional) `export XTERM=xterm`
- `screen /dev/ttyUSB0 115200`

1
rush00

Submodule rush00 deleted from e4ea057ebf

83
rush_00/Makefile Normal file
View File

@@ -0,0 +1,83 @@
# frequency of the CPU (in Hz)
F_CPU = 16000000UL
TARGET = main
CC = avr-gcc
INCLUDES = -I.
AVRGCC_MCU_TYPE = atmega328p
AVRDUDE_MCU_TYPE = m328p
BAUD_RATE = 115200
PROGRAMMER_ID = arduino
# original firmware dump
DUMP_ORI = ../../ressources/dump_atmega328p_ori.hex
# Find all C source files in the current directory
SRC = $(wildcard *.c)
# Generate object file names from source file names
OBJ = $(SRC:.c=.o)
# Compiler flags
CFLAGS = -mmcu=$(AVRGCC_MCU_TYPE) -D F_CPU=$(F_CPU) $(INCLUDES) -Os
# Detect OS
OS := $(shell uname -s)
# Set Serial Port based on OS
ifeq ($(OS), Darwin) # macOS
SERIAL_PORT_1 := /dev/tty.usbserial-310 # $(shell ls /dev/tty.usb* 2>/dev/null | head -n 1) # should be : /dev/tty.usbserial-310
SERIAL_PORT_2 := /dev/tty.usbserial-110
else ifeq ($(OS), Linux) # Ubuntu/Linux
SERIAL_PORT_1 = /dev/ttyUSB0 # $(shell ls /dev/ttyUSB* 2>/dev/null | head -n 1) # should be : /dev/ttyUSB0
SERIAL_PORT_2 = /dev/ttyUSB1
endif
##
## RULES
##
all: hex flash
hex: $(TARGET).hex
# Compile each .c file to corresponding .o file
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
# Link all object files to create the binary
# avr-gcc : compiler for AVR microcontrollers, https://gcc.gnu.org/wiki/avr-gcc#Using_avr-gcc, https://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html
# -mmcu : the target microcontrolle (ATmega328P)
# -D : defines a preprocessor macro (#define F_CPU <value>)
# -o : output filename
$(TARGET).bin: $(OBJ)
$(CC) -mmcu=$(AVRGCC_MCU_TYPE) $(OBJ) -o $(TARGET).bin
# Convert binary to hex for flashing
# avr-objcopy : man avr-jobcopy, https://linux.die.net/man/1/avr-objcopy
# -O : specifies output format, Intel HEX
# some formats (list not found in any doc) :
# -O ihex : Used for flashing AVR chips
# -O binary : Raw binary file
# -O elf32-avr : Used for debugging
$(TARGET).hex: $(TARGET).bin
avr-objcopy -O ihex $(TARGET).bin $(TARGET).hex
# Flash the hex file to the microcontroller
# avr-dude : AVR Downloader/UploaDEr, upload firmware, https://avrdudes.github.io/avrdude, v6.3 https://download-mirror.savannah.gnu.org/releases/avrdude/avrdude-doc-6.3.pdf
# -p : specifies the microcontroller -> m328p
# -c : programmer-id
# -b : baud rate for serial communication
# -P : the serial port, found with `ls /dev/tty*` -> /dev/ttyUSB0
# -U : Uploads (w = write) the HEX firmware file to the flash memory
# (-v : verbose info dump)
flash:
avrdude -p $(AVRDUDE_MCU_TYPE) -c $(PROGRAMMER_ID) -b $(BAUD_RATE) -P $(SERIAL_PORT_1) -U flash:w:$(TARGET).hex
avrdude -p $(AVRDUDE_MCU_TYPE) -c $(PROGRAMMER_ID) -b $(BAUD_RATE) -P $(SERIAL_PORT_2) -U flash:w:$(TARGET).hex
restore:
avrdude -p $(AVRDUDE_MCU_TYPE) -c $(PROGRAMMER_ID) -b $(BAUD_RATE) -P $(SERIAL_PORT) -U flash:w:$(DUMP_ORI)
clean:
rm -f main.hex main.bin $(OBJ)
.PHONY : all clean hex flash restore

37
rush_00/README.md Normal file
View File

@@ -0,0 +1,37 @@
# Parallel Development Plan (chat gpt :p)
| Task | Developer | Dependencies |
| ------------------------------------------- | ------------ | ----------------------------------------------- |
| Configure I2C (Master/Slave) | **Person A** | None |
| Configure GPIOs (Buttons & LEDs) | **Person B** | None |
| Implement button interrupt handling | **Person B** | Needs GPIO setup |
| Implement LED countdown sequence | **Person B** | Needs GPIO setup |
| Implement I2C send & receive functions | **Person A** | Needs I2C setup |
| Implement game state transitions | **Person A** | Needs I2C communication & button press handling |
| Implement reaction detection & winner logic | **Person A** | Needs game state management & button interrupts |
| Implement LED signals for winner/loser | **Person B** | Needs reaction detection |
| Implement game reset logic | **Person A** | Needs winner detection |
| Sync both MCUs on game start | **Person A** | Needs I2C and button handling |
## How Each Person Works in Parallel
### **Person A: I2C & Game Logic**
- Starts with I2C initialization and communication functions.
- Implements game state management (waiting, countdown, reaction, result).
- Manages synchronization between the two MCUs.
- Detects the winner and resets the game.
### **Person B: Buttons & LEDs**
- Sets up buttons and interrupts.
- Implements debounce mechanism to avoid false triggers.
- Handles the countdown sequence using LEDs.
- Displays winner/loser using LEDs.
## Collaboration Strategy
1. **Step 1:** Work independently on separate modules.
2. **Step 2:** Integrate button presses with game state transitions.
3. **Step 3:** Test button presses and countdown independently.
4. **Step 4:** Merge both parts and test full game logic with I2C communication.

53
rush_00/bitmanip.h Normal file
View File

@@ -0,0 +1,53 @@
#ifndef BITMANIP_H
#define BITMANIP_H
#include "utils.h"
// Bit operations 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)))
// Get arguments from tuple-like definitions
#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 elements
// #define SET_ELEM(...) SET(CONCAT(PORT, GET_PORT(__VA_ARGS__)), GET_BIT(__VA_ARGS__)) // version for "LED1 B, D1" without parenthesis
#define SET_ELEM(elem) SET(CONCAT(PORT, GET_PORT(elem)), GET_BIT(elem))
#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)
// Bit definitions
#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 LED2 (B, D2)
#define LED3 (B, D3)
#define LED4 (B, D4)
#define BUTTON1 (D, SW1)
#define BUTTON2 (D, SW2)
#endif // BITMANIP_H

18
rush_00/game.c Normal file
View File

@@ -0,0 +1,18 @@
#include "rush_header.h"
void timer() {
flash_led(D3);
_delay_ms(500);
flash_led(D3);
_delay_ms(500);
flash_led(D3);
_delay_ms(500);
flash_led(D3);
_delay_ms(500);
turn_on_led(D3);
}
void launch_game() {
// timer();
write_one_byte_data(0x01);
}

8
rush_00/interrupt.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef INTERRUPT_H
#define INTERRUPT_H
// 7.3.1 : SREG AVR Status Register
#define ENABLE_GLOBAL_INTERRUPT (1<<7)
#define DISABLE_GLOBAL_INTERRUPT (0<<7)
#endif // INTERRUPT_H

66
rush_00/interrupts.c Normal file
View File

@@ -0,0 +1,66 @@
#include "rush_header.h"
volatile Role role = WAITING;
void setup_button_interrupt() { // interruption SW1 (PD2)
EICRA |= (1 << ISC01); // trigger on falling edge for INT0
EIMSK |= (1 << INT0); // Activate INT0
SREG |= (1 << SREG_I);
}
ISR(INT0_vect) { // interruption SW1 (PD2)
if (!TEST_PIN(BUTTON1)) {
_delay_ms(30);
flash_led(D4);
if (role == MASTER) {
// write_one_byte_data(0x01);
read_one_byte_data();
} else if (role == SLAVE) {
// PORTD &= ~(1 << PD2); // Pull PD2 low (active LOW signal)
// _delay_ms(10); // Give master time to catch the signal
// PORTD |= (1 << PD2); // Reset line HIGH
}
}
}
ISR(TWI_vect) { // interruption slave receive data, Table 12-1 : 25, 2-wire Serial Interface
uint8_t status = TWSR & MASK_WITHOUT_LAST_3;
switch (status) {
// Slave Receiver cases
case TW_SR_SLA_ACK: // SLA+W received, ACK sent
// flash_led(D4);
turn_on_led_2_light();
break;
case TW_SR_DATA_ACK: // data received, ACK sent
if (role == WAITING) {
role = SLAVE;
}
received_data = TWDR; // store received data
break;
case TW_SR_STOP: // STOP or REPEATED START
break;
case TW_SR_DATA_NACK: // data received but slave answered NACK (no ACK an means end of communication or error)
break;
// Slave Transmitter cases
case TW_ST_SLA_ACK: // SLA+R received, ACK sent - First byte to be transmitted
flash_led(D4);
TWDR = 0x10; // send first data byte
break;
case TW_ST_DATA_ACK: // data sent, ACK received - Additional bytes can be sent
TWDR = 0x10; // send next data byte
break;
case TW_ST_DATA_NACK: // data sent, NACK received - No more data requested
break; // master doesn't want more data
case TW_ST_LAST_DATA: // last data byte sent, ACK received
break; // All data sent
default:
break;
}
TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA) | (1 << TWIE); // Clear interrupt flag and enable next transfer
}

52
rush_00/main.c Normal file
View File

@@ -0,0 +1,52 @@
#include "rush_header.h"
#define BLINK_PRESCALE_VALUE 1024 // can be 1, 8, 64, 256, 1024
#define BLINK_DUTY_CYCLE 10
void flash_led(int bit) {
SET(DDRB, bit);
SET(PORTB, bit);
_delay_ms(100);
CLEAR(PORTB, bit);
}
void turn_on_led(int bit) {
SET(DDRB, bit);
SET(PORTB, bit);
}
void turn_on_led_2_light() {
uint8_t duty = 10;
// Set PB1 (OC1A) as output
DDRB |= (1 << PB1);
// Configure Timer1 for Fast PWM, 8-bit mode
TCCR1A = (1 << COM1A1) | (1 << WGM10); // Clear OC1A on compare match, Fast PWM
TCCR1B = (1 << WGM12) | (1 << CS11); // Prescaler 8
// Set duty cycle (0-255, where 255 = fully ON, 0 = fully OFF)
OCR1A = duty;
}
void turn_off_led(int bit) {
SET(DDRB, bit);
CLEAR(PORTB, bit);
}
void blink_led_2(int period) {
MODE_OUTPUT(LED2);
SET(TCCR1A, WGM11); // Table 16-4 : set timer in Fast PWM (Pulse With Modulation) mode with TOP = ICR1 (Mode 14)
SET(TCCR1B, WGM12);
SET(TCCR1B, WGM13);
SET(TCCR1A, COM1A1); // Table 16-2 : non-inverting mode, the LED will be ON for DUTY_CYCLE% of the time (CLEAR OC1A on compare match, SET OC1A at BOTTOM)
ICR1 = TIME_MS(period, BLINK_PRESCALE_VALUE); // Table 16-4 : set the period (compare TOP value)
OCR1A = TIME_MS(PERCENT(BLINK_DUTY_CYCLE, period), BLINK_PRESCALE_VALUE); // 16.9.3 : set the duty cycle to DUTY_CYCLE% of the time on channel A -> OC1A (alternate function of PORTB1, aka LED2) is cleared when TCNT1 (the counter value) equals OCR1A
TCCR1B |= (PRESCALE_SET(BLINK_PRESCALE_VALUE)); // start the timer with the prescaler
}
int main() {
MODE_INPUT(BUTTON1); // set as input
SET_ELEM(BUTTON1); // pull-up resistor on
twi_init_slave();
get_role();
setup_button_interrupt();
// launch_game();
while (1);
}

22
rush_00/roles.c Normal file
View File

@@ -0,0 +1,22 @@
#include "rush_header.h"
void get_role() {
int end = FALSE;
while(!end) {
_delay_ms(50);
if (role == SLAVE) {
end = TRUE;
// MODE_OUTPUT(BUTTON1);
continue;
}
if (!IS_PIN_SET(BUTTON1)) {
continue;
}
end = TRUE;
turn_on_led(D1);
role = MASTER;
twi_stop_slave();
twi_init_master();
write_one_byte_data(0x01);
}
}

72
rush_00/rush_header.h Normal file
View File

@@ -0,0 +1,72 @@
#ifndef RUSH_HEADER_H
#define RUSH_HEADER_H
#include <avr/io.h>
#include <util/delay.h>
#include <util/twi.h>
#include <avr/interrupt.h>
#include "utils.h"
#include "bitmanip.h"
#include "timer.h"
#include "usart.h"
#include "interrupt.h"
// TWI
// table 22-7 : prescale sets
#define TWI_PRESCALE_VALUE 1 // can be 1, 4, 16, 64
#define TWI_PRESCALE_SET(value) \
((value) == 1 ? (0<<TWPS1 | 0<<TWPS0) : \
(value) == 4 ? (0<<TWPS1 | 1<<TWPS0) : \
(value) == 16 ? (1<<TWPS1 | 0<<TWPS0) : \
(value) == 64 ? (1<<TWPS1 | 1<<TWPS0) : 0x00)
// 100kHz I2C
#define TWI_FREQ 100000UL
// Slave address
#define SLAVE_ADDRESS 42 // 22.3.3 : address 0000000 and 1111xxx are reservedm 42 is 0101010
// 22.7.1 : TWCR, Master Transmitter Mode
#define SEND_START_CONDITION ((1<<TWINT) | (1<<TWEN)) | (1<<TWSTA)
#define SEND_CONTINUE_TRANSMISSION ((1<<TWINT) | (1<<TWEN))
#define SEND_STOP_CONDITION ((1<<TWINT) | (1<<TWEN)) | (1<<TWSTO)
#define SEND_ACKNOWLEDGE ((1<<TWINT) | (1<<TWEN) | (1<<TWEA))
#define SEND_NACKNOWLEDGE ((1<<TWINT) | (1<<TWEN))
#define MASK_WITHOUT_LAST_3 0xF8 // 11111000
// FUNCTION PROTOTYPES
// main.c
void flash_led();
void blink_led_2();
void turn_on_led(int bit);
void turn_on_led_1_light();
void turn_on_led_2_light();
void turn_off_led(int bit);
// twi.c
void twi_init_slave(void);
void twi_stop_slave(void);
void twi_init_master();
void twi_start();
void twi_send_addr(uint8_t addr_w);
void write_one_byte_data(uint8_t data);
uint8_t read_one_byte_data();
void twi_write(uint8_t data);
uint8_t twi_read(uint8_t ack);
void twi_stop();
// interupts.c
void setup_button_interrupt();
void setup_button_role();
// roles.c
void get_role();
// game.c
void launch_game();
// GLOBAL VARIABLES
typedef enum {
WAITING,
MASTER,
SLAVE
} Role;
extern volatile Role role;
extern volatile uint8_t received_data;
#endif // RUSH_HEADER_H

27
rush_00/timer.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef TIMER_H
#define TIMER_H
// table 16-5 : prescale sets
#define PRESCALE_SET(value) \
((value) == 1 ? (0<<CS12 | 0<<CS11 | 1<<CS10) : \
(value) == 8 ? (0<<CS12 | 1<<CS11 | 0<<CS10) : \
(value) == 64 ? (0<<CS12 | 1<<CS11 | 1<<CS10) : \
(value) == 256 ? (1<<CS12 | 0<<CS11 | 0<<CS10) : \
(value) == 1024? (1<<CS12 | 0<<CS11 | 1<<CS10) : \
(0<<CS12 | 0<<CS11 | 0<<CS10))
#define TIME_MS(ms, prescale_value) (((F_CPU / prescale_value) * ms) / 1000)
// Table 16-4 : Waveform Generation Mode Bit Description
#define CTC_TOP_OCR1A_IN_TCCR1B (0<<WGM13 | 1<<WGM12)
#define CTC_TOP_OCR1A_IN_TCCR1A (0<<WGM11 | 0<<WGM10)
#define CTC_TOP_ICR1_IN_TCCR1B (1<<WGM13 | 1<<WGM12)
#define CTC_TOP_ICR1_IN_TCCR1A (0<<WGM11 | 0<<WGM10)
#define FAST_PWM_TOP_OCR1A_IN_TCCR1B (1<<WGM13 | 1<<WGM12)
#define FAST_PWM_TOP_OCR1A_IN_TCCR1A (1<<WGM11 | 1<<WGM10)
#define FAST_PWM_TOP_ICR1_IN_TCCR1B (1<<WGM13 | 1<<WGM12)
#define FAST_PWM_TOP_ICR1_IN_TCCR1A (1<<WGM11 | 0<<WGM10)
// 16.11.8 : Timer/Counter1 Interrupt Mask Register
#define INTERRUPT_ENABLE_CHANNEL_A (1 << OCIE1A)
#define INTERRUPT_DISABLE_CHANNEL_A (0 << OCIE1A)
#endif // TIMER_H

105
rush_00/twi.c Normal file
View File

@@ -0,0 +1,105 @@
#include "rush_header.h"
volatile uint8_t received_data = 0;
void twi_init_slave(void) {
TWAR = (SLAVE_ADDRESS << 1);
TWCR = (1 << TWEN) | (1 << TWEA) | (1 << TWIE); // Enable TWI, enable ACK, and enable TWI interrupt
SREG |= (1 << SREG_I);
}
void twi_stop_slave(void) {
// TWCR = 0x00; // Disable TWI interrupts and TWI module
// TWAR = 0x00; // Optionally, clear the TWI address register
}
void twi_init_master() {
TWSR = TWI_PRESCALE_SET(TWI_PRESCALE_VALUE); // 22.9.3 : (Status Register) set prescaler
TWBR = ((F_CPU / TWI_FREQ) - 16) / (2 * TWI_PRESCALE_VALUE); // 22.9.1 : (Bit Rate Register) set SCL frequency (formula from datasheet, 22.5.2)
}
void twi_start() {
TWCR = SEND_START_CONDITION; // 22.9.2 : (Control Register) send Start condition (22.7.1) ! writting 1 to TWINT clears it (set it to 0)
while (!(TEST(TWCR, TWINT))); // p225 example code : Wait for TWINT Flag set. This indicates that the START condition has been transmitted
uint8_t status = TWSR & MASK_WITHOUT_LAST_3; // p225 example code : Check value of TWI Status Register. Mask prescaler bits. If status different from START go to ERROR
if (status != TW_START && status != TW_REP_START) {
TWCR = SEND_STOP_CONDITION;
return;
}
}
void twi_send_addr(uint8_t addr_r_w) {
TWDR = addr_r_w; // 22.9.4 : (Data Register) load data into TWDR register
TWCR = SEND_CONTINUE_TRANSMISSION; // p225 example code : Load SLA_W into TWDR Register. Clear TWINT bit in TWCR to start transmission of address
while (!(TEST(TWCR, TWINT))); // p225 example code : Wait for TWINT Flag set. This indicates that the SLA+W has been transmitted, and ACK/NACK has been received
uint8_t status = TWSR & MASK_WITHOUT_LAST_3; // Check value of TWI Status Register. Mask prescaler bits. If status different from MT_SLA_ACK go to ERROR
if (status != TW_MT_SLA_ACK) {
TWCR = SEND_STOP_CONDITION;
return;
}
}
void twi_write(uint8_t data) {
TWDR = data; // 22.9.4 : (Data Register) load data into TWDR register
TWCR = SEND_CONTINUE_TRANSMISSION; // p225 example code : Load DATA into TWDR Register. Clear TWINT bit in TWCR to start transmission of data
while (!(TEST(TWCR, TWINT))); // p225 example code : Wait for TWINT Flag set. This indicates that the DATA has been transmitted, and ACK/NACK has been received
uint8_t status = TWSR & MASK_WITHOUT_LAST_3; // p225 example code : Check value of TWI Status Register. Mask prescaler bits. If status different from MT_DATA_ACK go to ERROR
if (status != TW_MT_DATA_ACK) {
TWCR = SEND_STOP_CONDITION;
return;
}
}
uint8_t twi_read(uint8_t ack) {
flash_led(D1); // Before setting TWCR
if (ack) {
TWCR = SEND_ACKNOWLEDGE; // Send ACK to request more data
} else {
TWCR = SEND_NACKNOWLEDGE; // Send NACK to indicate last byte read
}
// while (!(TEST(TWCR, TWINT))); // Wait for data reception
// Add a timeout to prevent infinite waiting
uint16_t timeout = 1000;
while (!(TEST(TWCR, TWINT)) && timeout > 0) {
timeout--;
_delay_us(10);
}
flash_led(D2); // After TWINT set or timeout
if (timeout == 0) {
// Timeout occurred, slave didn't respond
flash_led(D3); // Indicate timeout
TWCR = SEND_STOP_CONDITION;
return 0xFF; // Error code for timeout
}
uint8_t status = TWSR & MASK_WITHOUT_LAST_3;
if (status != TW_MR_DATA_ACK && status != TW_MR_DATA_NACK) {
TWCR = SEND_STOP_CONDITION;
return 0;
}
flash_led(D4); // Indicate status error
return TWDR;
}
void twi_stop() {
TWCR = SEND_STOP_CONDITION;
}
void write_one_byte_data(uint8_t data) {
twi_start();
twi_send_addr((SLAVE_ADDRESS << 1) | TW_WRITE); // Send Slave address with Write bit
twi_write(data); // write data byte
twi_stop();
}
uint8_t read_one_byte_data() {
twi_start();
twi_send_addr((SLAVE_ADDRESS << 1) | TW_READ); // Send Slave address with Write bit
uint8_t data = twi_read(FALSE); // Read data with NACK (only one byte expected)
twi_stop();
return data;
}

31
rush_00/usart.h Normal file
View File

@@ -0,0 +1,31 @@
#ifndef USART_H
#define USART_H
#define BAUD_PRESCALER(usart_baudrate) (DIV_ROUND_CLOSEST(F_CPU, (16 * usart_baudrate)) - 1)
// Table 20-8 : Mode Selection (USART Mode SELect)
#define ASYNCHRONOUS (0<<UMSEL01 | 0<<UMSEL00)
#define SYNCHRONOUS (0<<UMSEL01 | 1<<UMSEL00)
// Table 20-9 : Parity Bit Selection (USART Parity Mode)
#define PARITY_DISABLED (0<<UPM01 | 0<<UPM00)
#define PARITY_EVEN (1<<UPM01 | 0<<UPM00)
#define PARITY_ODD (1<<UPM01 | 1<<UPM00)
// Table 20-10 : Stop Bit Selection (USART Stop Bit Select)
#define STOP_ONE_BIT (0<<USBS0)
#define STOP_TWO_BIT (1<<USBS0)
// Table 20-11 : Data Bit Selection (USART Character SiZe)
#define DATA_FIVE_BIT (0<<UCSZ02 | 0<<UCSZ01 | 0<<UCSZ00)
#define DATA_SIX_BIT (0<<UCSZ02 | 0<<UCSZ01 | 1<<UCSZ00)
#define DATA_SEVEN_BIT (0<<UCSZ02 | 1<<UCSZ01 | 0<<UCSZ00)
#define DATA_EIGHT_BIT (0<<UCSZ02 | 1<<UCSZ01 | 1<<UCSZ00)
#define DATA_NINE_BIT (1<<UCSZ02 | 1<<UCSZ01 | 1<<UCSZ00)
// 20.11.3 : USART Control and Status Register B (UCSRnB)
#define RECEIVER_DISABLED (0<<RXEN0)
#define RECEIVER_ENABLED (1<<RXEN0)
#define TRANSMITTER_DISABLED (0<<TXEN0)
#define TRANSMITTER_ENABLED (1<<TXEN0)
#define INTERRUPT_RECEIVER_DISABLED (0<<RXCIE0)
#define INTERRUPT_RECEIVER_ENABLED (1<<RXCIE0)
#define INTERRUPT_TRANSMITTER_DISABLED (0<<TXCIE0)
#define INTERRUPT_TRANSMITTER_ENABLED (1<<TXCIE0)
#endif // USART_H

23
rush_00/utils.h Normal file
View File

@@ -0,0 +1,23 @@
#ifndef UTILS_H
#define UTILS_H
// 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)
// mathematics
#define PERCENT(percent, total) (((float)percent / 100) * total)
#define DIV_ROUND_CLOSEST(n, d) ((((n) < 0) == ((d) < 0)) ? (((n) + (d)/2)/(d)) : (((n) - (d)/2)/(d)))
// text
#define SWITCH_CASE(ch) (((ch) >= 'A' && (ch) <= 'Z') || ((ch) >= 'a' && (ch) <= 'z') ? ((ch) ^ (1 << 5)) : (ch))
// boolean
#define TRUE 1
#define FALSE 0
#endif // UTILS_H