#include <avr/io.h>
#include <util/delay.h>

// test with https://www.onlinegdb.com/online_c_compiler
// // V1
//
// // macro to extract port and bit from a single pin
// #define _PORT(pin)	((pin) >> 3)
// #define _BIT(pin)	((pin) & 0x07) // 0x07 is 00000111
//
// // helper macros for port name concatenation
// #define _CONCAT(a, b) a ## b
// #define PORT_REGISTER(pin)	_CONCAT(PORT, _PORT(pin))
// #define DDR_REGISTER(pin)	_CONCAT(DDR, _PORT(pin))
// #define PIN_REGISTER(pin)	_CONCAT(PIN, _PORT(pin))
//
// // Macros to set/clear/toggle specific bit
// #define SET(REGISTER, PIN)		REGISTER |= 1 << _BIT(PIN)
// #define CLEAR(REGISTER, PIN)	REGISTER &= ~(1 << _BIT(PIN))
// #define TOGGLE(REGISTER, PIN)	REGISTER ^= 1 << _BIT(PIN)
// #define MODE_OUTPUT(PIN)		(DDR_REGISTER(PIN) |= 1 << _BIT(PIN))
// #define MODE_INPUT(PIN)			(DDR_REGISTER(PIN) &= ~(1 << _BIT(PIN)))
//
// // Test and check macros
// #define TEST_PIN(PIN)			(PIN_REGISTER(PIN) & (1 << _BIT(PIN)))
// #define IS_SET(PIN)			(TEST(PIN) != 0)
// #define IS_CLEAR(PIN)		(TEST(PIN) == 0)
//
// // Pin definitions
// #define D1 (0 + (1 << 3))   // Port B, bit 0
// #define D2 (1 + (1 << 3))   // Port B, bit 1
// #define D3 (2 + (1 << 3))   // Port B, bit 2
// #define D4 (4 + (1 << 3))   // Port B, bit 4
// #define SW1 (2 + (3 << 3))  // Port D, bit 2
// #define SW2 (4 + (3 << 3))  // Port D, bit 4

// // V2
//
// // Define the ports
// #define PORT_B    0   // Port A (represented by 0)
// #define PORT_C    1   // Port B (represented by 1)
// #define PORT_D    2   // Port C (represented by 2)
//
// // Macros to extract the port and bit
// #define _PORT_INT(pin)   ((pin) >> 3)            // Extract the port
// #define _PORT(pin)  \
//     ((_PORT_INT(pin)) == PORT_B ? 'B' :  \
//     ((_PORT_INT(pin)) == PORT_C ? 'C' :  \
//     ((_PORT_INT(pin)) == PORT_D ? 'D' :  \
// 	'X')))
// #define _BIT(pin)        ((pin) & 0x07)              // Extract the bit
//
// // Macros to set/clear/toggle specific bit
// #define SET(REGISTER, PIN)		REGISTER |= 1 << _BIT(PIN)
// #define CLEAR(REGISTER, PIN)	REGISTER &= ~(1 << _BIT(PIN))
// #define TOGGLE(REGISTER, PIN)	REGISTER ^= 1 << _BIT(PIN)
// #define MODE_OUTPUT(PIN)		(_PORT(PIN) |= 1 << _BIT(PIN))
// #define MODE_INPUT(PIN)			(_PORT(PIN) &= ~(1 << _BIT(PIN)))
//
// // Test and check macros
// #define TEST(PIN)			(PIN_REGISTER(PIN) & (1 << _BIT(PIN)))
// #define IS_SET(PIN)			(TEST(PIN) != 0)
// #define IS_CLEAR(PIN)		(TEST(PIN) == 0)
//
// // Define each LED's port and bit using macros
// #define D1 (PORT_B << 3 | 0)  // LED1 is on Port B, bit 0
// #define D2 (PORT_B << 3 | 1)  // LED2 is on Port A, bit 1
// #define D3 (PORT_B << 3 | 2)  // LED3 is on Port C, bit 2
// #define D4 (PORT_B << 3 | 4)  // LED4 is on Port C, bit 4

// V0

#define SET(REGISTER, BIT)		REGISTER |= 1 << BIT
#define CLEAR(REGISTER, BIT)	REGISTER &= ~(1 << BIT)
#define TEST(REGISTER, BIT)		REGISTER & 1 << BIT
#define TEST_PIN(PORT, BIT)		PIN ## PORT & 1 << BIT
#define TOGGLE(REGISTER, BIT)	REGISTER ^= 1 << BIT
#define MODE_INPUT(PORT, BIT)	CLEAR(DDR ## PORT, BIT)
#define MODE_OUTPUT(PORT, BIT)	SET(DDR ## PORT, BIT)
#define IS_PIN_SET(PORT, BIT)	(TEST_PIN(PORT, BIT)) == 0
#define IS_PIN_CLEAR(PORT, BIT)	(TEST_PIN(PORT, BIT)) == 1

#define D1 0
#define D2 1
#define D3 2
#define D4 4
#define SW1 2
#define SW2 4

int main()
{
	MODE_OUTPUT(B, D1);
	MODE_INPUT(D, SW1);
	while(1) {
		if (IS_PIN_SET(D, SW1)) {
			SET(PORTB, D1);
 		} else {
			CLEAR(PORTB, D1);
		}
	}
	return 0;
}