I'm writing an initialization function on an ATTiny441 to set the data direction register (DDR) for Port A or B based on the physical pin number.
So far my implementation seems a bit clunky. Below is the initialization function in nrf.c
that I'll call in main.c
:
/* nrf.c */
#import <avr/io.h>
#import "t441.h"
bool ce_port_a;
uint8_t ce_bit;
void nrf_init(uint8_t ce_pin,
uint8_t csn_pin)
{
/* Map CE pin */
t441_map_pins(ce_pin, &ce_bit, &ce_port_a);
/* Set CE to output */
if(ce_port_a) DDRA |= BIT(ce_bit);
else DDRB |= BIT(ce_bit);
/* Clear CE */
_nrf_toggle_ce(0);
/* ... */
}
In the same nrf.c
, here's the function used to toggle the CE pin:
/* nrf.c */
void _nrf_toggle_ce(uint8_t direction)
{
/* Set CE */
if(direction) ce_port_a ? SET_BIT(PORTA, ce_bit) : SET_BIT(PORTB, ce_bit);
/* Clear CE */
else ce_port_a ? CLEAR_BIT(PORTA, ce_bit) : CLEAR_BIT(PORTB, ce_bit);
}
(Note the SET_BIT() and CLEAR_BIT() functions are defined elsewhere, but I assume that they're descriptive enough.)
And, finally, here's the function in t441.c
that maps the physical pin number to a Port and bit number:
/* t441.c */
uint8_t t441_port_b_map[4] = {0, 1, 3, 2};
void t441_map_pins(uint8_t pin_num, uint8_t *port_pin_num, bool *port_a)
{
if(pin_num < 6)
{
/* Pin is on Port B */
*port_a = false;
*port_pin_num = t441_port_b_map[pin_num - 2];
}
else
{
/* Pin is on Port A */
*port_a = true;
*port_pin_num = 13 - pin_num;
}
}
Question: Is there a simpler or more elegant way to approach this? I'm somewhat concerned with program memory usage but mainly with code re-usability -- e.g. having to significantly change things if using a microcontroller with more than two IO ports.
(I'll move this to Stack Overflow if appropriate.)