Source

rfid / avrfid2.c

#include <avr/io.h>

/* Use r16 and r17 to track the state of the pins */
volatile  register  uint8_t r16 __asm__("r16"); 
volatile  register  uint8_t r17 __asm__("r17"); 

/**
 * Delay a specific number of clock cycles.
 *
 * rjmp is 2 clocks, nop is 1.
 * So do one nop if the delay is an odd value and then rjmp's for n/2.
 */
static inline void
delay(
	const uint8_t n
)
{
	switch (n/2)
	{
	case 8: asm("rjmp .+0");
	case 7: asm("rjmp .+0");
	case 6: asm("rjmp .+0");
	case 5: asm("rjmp .+0");
	case 4: asm("rjmp .+0");
	case 3: asm("rjmp .+0");
	case 2: asm("rjmp .+0");
	case 1: asm("rjmp .+0");
	case 0: break;
	}

	if (n % 2 == 1)
		asm("nop");
}


static void
__attribute__((__always_inline__))
toggle(	
	const uint8_t n
)
{
	asm(
		"eor r16, r17\n"
		"out 0x17, r16\n"
	);

	if (n > 2)
		delay(n-2);
}


static void
__attribute__((__always_inline__))
baseband_0(void
	//uint8_t startloop
)
{
	toggle(4); // 4
	toggle(4); // 8
	toggle(4); // 12
	toggle(4); // 16
	toggle(4); // 20
	toggle(4); // 24
	toggle(4); // 28
	toggle(4); // 32
	toggle(4); // 36
	toggle(4); // 40
	toggle(4); // 44
	toggle(4); // 48
	toggle(4); // 52
}


static void
__attribute__((__always_inline__))
baseband_1(void
	//uint8_t startloop
)
{
	toggle(5); //  5
	toggle(5); // 10
	toggle(5); // 15
	toggle(5); // 20
	toggle(5); // 25
	toggle(5); // 30
	toggle(5); // 35
	toggle(5); // 40
	toggle(5); // 45
	toggle(5); // 50
}


static inline void
header(void)
{
	baseband_0();
	baseband_0();
	baseband_0();
	baseband_1();
	baseband_1();
	baseband_1();
}


static void
__attribute__((__always_inline__))
manchester_bit(
	const uint8_t x
)
{
	if (x & 1)
	{
		baseband_1();
		baseband_0();
	} else {
		baseband_0();
		baseband_1();
	}
}

static inline void
__attribute__((__always_inline__))
manchester(
	const uint32_t x,
	const uint8_t bits
)
{
	switch(bits - 1)
	{
	case 20: manchester_bit(x >> 20);
	case 19: manchester_bit(x >> 19);
	case 18: manchester_bit(x >> 18);
	case 17: manchester_bit(x >> 17);
	case 16: manchester_bit(x >> 16);
	case 15: manchester_bit(x >> 15);
	case 14: manchester_bit(x >> 14);
	case 13: manchester_bit(x >> 13);
	case 12: manchester_bit(x >> 12);
	case 11: manchester_bit(x >> 11);
	case 10: manchester_bit(x >> 10);
	case  9: manchester_bit(x >>  9);
	case  8: manchester_bit(x >>  8);
	case  7: manchester_bit(x >>  7);
	case  6: manchester_bit(x >>  6);
	case  5: manchester_bit(x >>  5);
	case  4: manchester_bit(x >>  4);
	case  3: manchester_bit(x >>  3);
	case  2: manchester_bit(x >>  2);
	case  1: manchester_bit(x >>  1);
	case  0: manchester_bit(x >>  0);
	}
}


#define HID_MFG_CODE        0x01002  // Do not modify
#define HID_SITE_CODE       42
#define HID_UNIQUE_ID       23946     // May be written on the back of the card

static void
__attribute__((__noinline__))
//__attribute__((section(".fini8")))
hid_output(void)
{
	header();
	asm("/* hid_mfg_code */\n");
	manchester(HID_MFG_CODE, 20);
	asm("/* hid_site_code */\n");
	manchester(HID_SITE_CODE, 8);
	asm("/* hid_unique_id */\n");
	manchester(HID_UNIQUE_ID, 16);
	asm("/* hid_parity */\n");
	manchester(0, 1);
}

int
__attribute__((section(".init9")))
main(void)
{
	r16 = 0;
	r17 = _BV(PINB3) | _BV(PINB4);

	while (1)
		hid_output();
}