// MAIN_test.c /* Copyright (C) 2016 H.Poetzl ** ** This program is free software: you can redistribute it and/or ** modify it under the terms of the GNU General Public License ** as published by the Free Software Foundation, either version ** 2 of the License, or (at your option) any later version. ** ** PB0 ... AT_#SS ** PB1 ... AT_SCK ** PB2 ... AT_MOSI ** PB3 ... AT_MISO ** PB4 ... AT_PB4 ** PB5 ... AT_PB5 ** PB6 ... AT_#RTSPD ** PB7 ... AT_SEL ** ** PC0 ... AT_PIO0 ** PC1 ... AT_PIO1 ** PC2 ... AT_PIO2 ** PC3 ... AT_PIO3 ** PC4 ... AT_PIO4 ** PC5 ... AT_PIO5 ** PC6 ... AT_PIO6 ** PC7 ... AT_PIO7 ** ** PD0 ... AT_SCL ** PD1 ... AT_SDA ** ** PD2 ... AT_RXD1 ** PD3 ... AT_TXD1 ** ** PD5 ... AT_TXCAN ** PD6 ... AT_RXCAN ** ** PE0 ... AT_RXD0 ** PE1 ... AT_TXD0 ** ** PE2 ... AT_#STBY ** ** PE3 ... AT_LEDA ** PE4 ... AT_LEDB ** PE5 ... AT_LEDC ** ** PE6 ... AT_LVL_EN ** PE7 ... AT_INT7 ** ** PF0 ... AT_LED0 ** PF1 ... AT_LED1 ** PF2 ... AT_LED2 ** PF3 ... AT_LED3 ** ** PG0 ... AT_CFG */ #define CAN_PWR #define F_CPU 16000000 #include #include #include #include #include #include #include #define PN532_RELAX 1000 #define PN532_STATUS 0x02 #define PN532_WRITE 0x01 #define PN532_READ 0x03 #define PN532_READY 0x01 #define PN532_PREAMBLE 0x00 #define PN532_SCODE1 0x00 #define PN532_SCODE2 0xFF #define PN532_POSTAMBLE 0x00 #define PN532_HTOPN532 0xD4 #define PN532_CC_DIAGNOSE 0x00 #define PN532_CC_VERSION 0x02 #define PN532_CC_GENSTAT 0x04 #define PN532_CC_READREG 0x06 #define PN532_CC_WRITEREG 0x08 #define PN532_CC_READGPIO 0x0C #define PN532_CC_WRITEGPIO 0x0E #define PN532_CC_BAUDRATE 0x10 #define PN532_CC_SETPARAM 0x12 #define PN532_CC_SAMCONFIG 0x14 #define PN532_CC_POWERDOWN 0x16 #define PN532_CC_RFCONFIG 0x32 #define PN532_CC_RFREGTEST 0x58 #define PN532_CC_PASSIVE 0x4A #define PN532_CC_AUTOPOLL 0x60 #define RFCI_FIELD 0x01 /* 1 */ #define RFCI_TIMING 0x02 /* 3 */ #define RFCI_RETRY_DATA 0x04 /* 1 */ #define RFCI_RETRY_SELECT 0x05 /* 3 */ #define RFCI_TYPE_A_106 0x0A /* 11 */ #define RFCI_TYPE_A_212_424 0x0B /* 8 */ #define RFCI_TYPE_B 0x0C /* 3 */ #define RFCI_TYPE_14443_4 0x0D /* 9 */ #define LED_A (1 << 3) #define LED_B (1 << 4) #define LED_C (1 << 5) uint8_t buf[256]; uint64_t cycle = 0; uint8_t col = ~0; static uint8_t gpin[7] = { 0 }; static uint8_t gddr[7] = { 0 }; static uint8_t gport[7] = { 0 }; static uint8_t gmask[7] = { ~0, 0x80, ~0, ~0, 0x2C, ~0, ~0 }; static uint8_t mask[7]; static uint8_t tcnt[7][8] = {{ 0 }}; static const uint8_t msg_ff[] = { 0xFF, 0xFF, 0xFF, 0xFF }; static const uint8_t msg_aa[] = { 0xAA, 0xAA, 0xAA, 0xAA }; static const uint8_t msg_ok[] = { 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00 }; static const uint8_t msg_ver[] = { 0x00, 0x00, 0xFF, 0x06, 0xFA, 0xD5, 0x03, 0x32, 0x01, 0x06, 0x07, 0xE8, 0x00 }; static const uint8_t msg_nc[] = { 0x00, 0x00, 0xFF, 0x03, 0xFD, 0xD5, 0x4B, 0x00, 0xE0, 0x00 }; static const uint8_t msg_card1[] = { 0x00, 0x00, 0xFF, 0x0F, 0xF1, 0xD5, 0x4B, 0x01, 0x01, 0x03, 0x44, 0x20, 0x07, 0x04, 0x4E, 0x08, 0x32, 0x50, 0x38, 0x80, 0xDC, 0x00 }; static const uint8_t msg_card2[] = { 0x00, 0x00, 0xFF, 0x0F, 0xF1, 0xD5, 0x4B, 0x01, 0x01, 0x03, 0x44, 0x20, 0x07, 0x04, 0x70, 0x94, 0x3A, 0x50, 0x38, 0x80, 0x26, 0x00 }; static const uint8_t msg_card3[] = { 0x00, 0x00, 0xFF, 0x0C, 0xF4, 0xD5, 0x4B, 0x01, 0x01, 0x00, 0x04, 0x08, 0x04, 0xEB, 0xE9, 0xDD, 0x0B, 0x12, 0x00 }; static inline void uart0_tx(char chr) { while (!(UCSR0A & (1< '9') chr += 'A' - '9' - 1; uart0_tx(chr); } static inline void uart0_tx_byte(uint8_t val) { uart0_tx_hex(val >> 4); uart0_tx_hex(val & 0xF); } static inline void uart0_tx_uint16(uint16_t val) { uart0_tx_byte(val >> 8); uart0_tx_byte(val & 0xFF); } static inline void uart0_tx_uint32(uint32_t val) { uart0_tx_uint16(val >> 16); uart0_tx_uint16(val & 0xFFFF); } static inline void uart0_tx_uint64(uint64_t val) { uart0_tx_uint32(val >> 32L); uart0_tx_uint32(val & 0xFFFFFFFFL); } static inline void uart0_tx_newline(void) { if (col) { uart0_tx('\r'); uart0_tx('\n'); col = 0; } } static void uart0_tx_dump(const uint8_t *buf, uint8_t len) { uint8_t cnt; uart0_tx('\t'); for (cnt = 0; cnt < len; cnt++) { uart0_tx_byte(buf[cnt]); if (cnt != len - 1) uart0_tx('.'); } } static inline uint8_t spidata(uint8_t val) { SPDR = val; while (!(SPSR & (1<> bit) & 1) { if (tcnt[idx][bit] < 15) { uart0_tx('A' + idx); uart0_tx_hex(bit); if ((pin >> bit) & 1) uart0_tx('+'); else uart0_tx('-'); tcnt[idx][bit]++; } else if (tcnt[idx][bit] != 0xFF) { uart0_tx('A' + idx); uart0_tx_hex(bit); uart0_tx('!'); mask[idx] &= ~(1 << bit); tcnt[idx][bit] = 0xFF; } } } gpin[idx] = pin; } if ((msk ^ mask[idx]) || ((ddr ^ gddr[idx]) & gmask[idx]) || ((port ^ gport[idx]) & gmask[idx])) { uart0_tx_newline(); uart0_tx('A' + idx); uart0_tx(':'); uart0_tx(' '); uart0_tx_byte(pin); uart0_tx('/'); uart0_tx_byte(ddr); uart0_tx('/'); uart0_tx_byte(port); uart0_tx('|'); uart0_tx_byte(mask[idx]); uart0_tx(' '); uart0_tx('#'); uart0_tx_uint64(cycle); uart0_tx_newline(); gddr[idx] = ddr; gport[idx] = port; } } static inline void test_adc(uint8_t prev, uint8_t this) { uint8_t val = ADCH; if (val >= 0xF8) { uart0_tx('.'); } else { uart0_tx('&'); uart0_tx_hex(prev & 0x7); uart0_tx('='); uart0_tx_byte(val); } ADMUX = (ADMUX & ~0xF) | (this & 0x7); ADCSRA |= (1 << ADSC); // start acquisition } static inline uint8_t msg_cmp(const uint8_t *msg, uint8_t len) { uint8_t i; for (i=0; i> 4) & 1; buf[0] = PN532_CC_VERSION; pn532_write(buf, 1, 0); if (active) { if (!check_msg(msg_ok, sizeof(msg_ok))) uart0_tx('!'); if (!check_msg(msg_ver, sizeof(msg_ver))) uart0_tx('!'); } else { check_msg(msg_ff, sizeof(msg_ff)); } } ISR (BADISR_vect) { uart0_tx('$'); asm("jmp 0"); } void bad_pc(void) { uart0_tx('%'); asm("jmp 0"); } int check_btn(void) { return (!(PING & 1)); } void check_loop(void) { uint8_t prev = 0; DDRE = 0x40; // EN output PORTE = ~0x00; // EN = 1 PORTB = ~0x40; // !RTSPD = 0 _delay_ms(100); while (1) { check(0, PINA, DDRA, PORTA); check(1, PINB, DDRB, PORTB); check(2, PINC, DDRC, PORTC); check(3, PIND, DDRD, PORTD); check(4, PINE, DDRE, PORTE); check(5, PINF, DDRF, PORTF); check(6, PING, DDRG, PORTG); cycle++; if (check_btn()) return; uint8_t this = (cycle >> 10) & 0xFF; if (this ^ prev) { test_adc(prev, this); test_pn532(prev); if (!(this & 0xF)) { uart0_tx_newline(); uart0_tx('#'); uart0_tx_uint64(cycle); uart0_tx_newline(); } switch ((this >> 4) & 3) { case 0: // reset PN532 DDRE = 0x40; // EN output PORTB = ~0x40; // !RTSPD = 0 break; case 1: // activate PN532 PORTB = ~0x00; // !RTSPD = 1 _delay_ms(100); break; case 2: // reset PN532 DDRE = 0x00; // all input PORTB = ~0x40; // !RTSPD = 0 break; case 3: // PORTB = ~0x00; // !RTSPD = 1 _delay_ms(100); break; } #ifdef CAN_PWR PORTC = (PORTC & ~0xC) | // power modes ((this >> 4) & 0xC); #endif prev = this; } } } void init_adc(void) { ADMUX = 0; // start with ADC0 ADMUX |= (1 << REFS0); // VCC as reference ADMUX |= (1 << ADLAR); // left align ADCSRA = (7 << ADPS0); // 1:128 prescaler ADCSRB = (0 << ADTS0); // free running ADCSRA |= (1 << ADEN); // enable ADC ADCSRA |= (1 << ADSC); // start acquisition } void init_spi(void) { SPCR = (1<