Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- int sc_switch = 2;
- int sc_clk = 11; // OC2A!
- int sc_rst = 3;
- int sc_rxtx = 4;
- void setup() {
- Serial.begin(9600);
- pinMode(sc_switch, INPUT_PULLUP);
- digitalWrite(sc_clk, LOW);
- pinMode(sc_clk, OUTPUT);
- digitalWrite(sc_rst, LOW);
- pinMode(sc_rst, OUTPUT); // RST = true
- digitalWrite(sc_rxtx, LOW);
- pinMode(sc_rxtx, INPUT); // HiZ
- // 16bit speed counter
- TCCR1A = 0; // normal mode
- TCCR1B = _BV(CS10); // 16MHz
- TIMSK1 = _BV(TOIE1); // OVF int
- }
- volatile word timer_ovf_count;
- ISR(TIMER1_OVF_vect) {
- timer_ovf_count++;
- }
- void wait_card()
- {
- while (digitalRead(sc_switch) == HIGH) {
- delay(10);
- if (digitalRead(sc_switch) == HIGH) continue;
- delay(10);
- if (digitalRead(sc_switch) == HIGH) continue;
- delay(10);
- if (digitalRead(sc_switch) == HIGH) continue;
- break;
- }
- }
- int check_card()
- {
- if (digitalRead(sc_switch) == HIGH) {
- delay(10);
- if (digitalRead(sc_switch) != HIGH) return true;
- delay(10);
- if (digitalRead(sc_switch) != HIGH) return true;
- delay(10);
- if (digitalRead(sc_switch) != HIGH) return true;
- return false;
- }
- return true;
- }
- inline void tunedDelay(uint16_t delay) {
- uint8_t tmp=0;
- asm volatile("sbiw %0, 0x01 \n\t"
- "ldi %1, 0xFF \n\t"
- "cpi %A0, 0xFF \n\t"
- "cpc %B0, %1 \n\t"
- "brne .-10 \n\t"
- : "+r" (delay), "+a" (tmp)
- : "0" (delay)
- );
- }
- int rx_bits;
- word rx_delay1;
- word rx_delay2;
- word tx_delay;
- void set_baudrate_low()
- {
- // etu^-1 = 4MHz / 372 = 10752 bps
- rx_bits = 8 + 1 + 2; // 8 + parity + stop
- rx_delay1 = 110;
- rx_delay2 = 200;
- tx_delay = 200;
- }
- void set_baudrate_high()
- {
- // etu^-1 = 4MHz * 2 / 372 = 21504 bps
- rx_bits = 8 + 1 + 1; // 8 + parity + stop
- rx_delay1 = 50;
- rx_delay2 = 90;
- tx_delay = 90;
- }
- int rx_pos;
- int rx_buf[256]; // 10 or 11 bit
- word rx_timestamp[256];
- unsigned long last_rx_timestamp;
- void rx_byte()
- {
- int v = 0, d = 1, i;
- word t = TCNT1;
- tunedDelay(rx_delay1);
- for (i = 0; i < rx_bits; i++) {
- int b;
- tunedDelay(rx_delay2);
- b = digitalRead(sc_rxtx) == HIGH ? d : 0;
- v |= b;
- d <<= 1;
- }
- if (rx_pos < 256) {
- rx_buf[rx_pos] = v;
- rx_timestamp[rx_pos] = t;
- rx_pos++;
- }
- }
- unsigned long last_tx_timestamp;
- byte tx_byte(byte x)
- {
- int v = x, p, i;
- p = x;
- p = p ^ (p >> 4);
- p = p ^ (p >> 2);
- p = p ^ (p >> 1);
- if (p & 1) v |= 0x100; // parity
- v |= 0xFE00; // stop bit
- cli();
- word t = TCNT1;
- word th = timer_ovf_count;
- if ((TIFR1 & _BV(TOV1)) && t < 0x1000) {
- th++;
- }
- last_tx_timestamp = (((unsigned long)th) << 16) + t;
- sei();
- pinMode(sc_rxtx, OUTPUT); // Lo, start
- tunedDelay(tx_delay);
- for (i = 0; i < rx_bits; i++) {
- if (v & 1) {
- pinMode(sc_rxtx, INPUT); // HiZ
- } else {
- pinMode(sc_rxtx, OUTPUT); // Lo
- }
- tunedDelay(tx_delay);
- v >>= 1;
- }
- pinMode(sc_rxtx, INPUT); // HiZ, nen no tame
- //delay(10); // yukkuri
- return x;
- }
- void rx_bytes(long first_byte_timeout, long rest_bytes_timeout)
- {
- rx_pos = 0;
- long timeout = first_byte_timeout;
- while (timeout > 0) {
- timeout--;
- if (digitalRead(sc_rxtx) == LOW) {
- cli();
- word t = TCNT1;
- word th = timer_ovf_count;
- if ((TIFR1 & _BV(TOV1)) && t < 0x1000) {
- th++;
- }
- last_rx_timestamp = (((unsigned long)th) << 16) + t;
- sei();
- if (digitalRead(sc_rxtx) == HIGH) continue;
- if (digitalRead(sc_rxtx) == HIGH) continue;
- if (digitalRead(sc_rxtx) == HIGH) continue;
- if (digitalRead(sc_rxtx) == HIGH) continue;
- rx_byte();
- timeout = rest_bytes_timeout;
- }
- }
- }
- void dump_rx_buffer()
- {
- for (int i = 0; i < rx_pos; i++) {
- Serial.print("+");
- Serial.print(rx_buf[i], HEX);
- Serial.print(" ");
- Serial.println(rx_timestamp[i], HEX);
- }
- }
- void pre_connection()
- {
- digitalWrite(sc_rst, LOW); // RST = true
- pinMode(sc_rxtx, INPUT); // HiZ
- TCCR2A = 0; // disconnect CLK
- }
- byte i_counter = 0x00;
- void reset_card()
- {
- OCR2A = 1; // 16MHz / 4
- TCCR2A = _BV(COM2A0) | _BV(WGM21); // toggle A, CTC
- TCCR2B = _BV(CS20); // 16MHz
- // wait 400 clk = 100ms (+alpha) < 40k clk
- delay(100 + 100);
- // IO must be HIGH
- if (digitalRead(sc_rxtx) != HIGH) {
- Serial.println("!!! sc_rxtx != HIGH @ RST");
- }
- digitalWrite(sc_rst, HIGH); // RST = false
- set_baudrate_low();
- // wait ATR
- Serial.println("### Wait ATR");
- rx_bytes(400000L, 100000L);
- if (rx_pos > 0) {
- Serial.println("### Get ATR: ");
- dump_rx_buffer();
- } else {
- Serial.println("!!! No ATR");
- }
- set_baudrate_high();
- {
- Serial.println("### IFS");
- byte lrc = 0;
- lrc ^= tx_byte(0x00); // NAD
- lrc ^= tx_byte(0xC1); // PCB, S(IFS, REQ)
- lrc ^= tx_byte(1); // LEN
- lrc ^= tx_byte(254); // IFS max
- tx_byte(lrc);
- rx_bytes(400000L, 100000L);
- dump_rx_buffer();
- }
- i_counter = 0;
- }
- void command()
- {
- Serial.println("### run command");
- Serial.println("### INI");
- byte lrc = 0;
- lrc ^= tx_byte(0x00); // NAD
- lrc ^= tx_byte(i_counter); // PCB
- lrc ^= tx_byte(5); // LEN
- // INF
- lrc ^= tx_byte(0x90); // CLA
- lrc ^= tx_byte(0x30); // INS
- lrc ^= tx_byte(0x00); // P1
- lrc ^= tx_byte(0x00); // P2
- lrc ^= tx_byte(0x00); // Le
- // LRC
- tx_byte(lrc);
- rx_bytes(400000L, 100000L);
- dump_rx_buffer();
- i_counter ^= 0x40;
- byte cardId[6];
- cardId[0] = rx_buf[11];
- cardId[1] = rx_buf[12];
- cardId[2] = rx_buf[13];
- cardId[3] = rx_buf[14];
- cardId[4] = rx_buf[15];
- cardId[5] = rx_buf[16];
- Serial.println("### EMM benchmark");
- Serial.flush();
- unsigned long R = 1UL;
- for (int rshift = 0; rshift < 32; rshift++, R <<= 1) {
- unsigned long total = 0;
- for (int L = 0; L < 128 * 13; L += 13) {
- lrc = 0;
- lrc ^= tx_byte(0x00); // NAD
- lrc ^= tx_byte(i_counter); // PCB
- lrc ^= tx_byte(14 + 8 * 13); // LEN
- // INF
- lrc ^= tx_byte(0x90); // CLA
- lrc ^= tx_byte(0x36); // INS
- lrc ^= tx_byte(0x00); // P1
- lrc ^= tx_byte(0x00); // P2
- lrc ^= tx_byte(8 + 8 * 13);
- lrc ^= tx_byte(cardId[0]);
- lrc ^= tx_byte(cardId[1]);
- lrc ^= tx_byte(cardId[2]);
- lrc ^= tx_byte(cardId[3]);
- lrc ^= tx_byte(cardId[4]);
- lrc ^= tx_byte(cardId[5]);
- lrc ^= tx_byte(8 + 8 * 13 - 7); // EMM len
- lrc ^= tx_byte(0x00); // protocol
- for (int i = 0; i < 13; i++) {
- lrc ^= tx_byte(((L + i) >> 0) & 0xFF);
- lrc ^= tx_byte(((L + i) >> 8) & 0xFF);
- lrc ^= tx_byte(0x00);
- lrc ^= tx_byte(0x00);
- lrc ^= tx_byte((R >> 0) & 0xFF);
- lrc ^= tx_byte((R >> 8) & 0xFF);
- lrc ^= tx_byte((R >> 16) & 0xFF);
- lrc ^= tx_byte((R >> 24) & 0xFF);
- }
- lrc ^= tx_byte(0x00); // Le
- // LRC
- tx_byte(lrc);
- rx_bytes(4000000L, 100000L);
- //dump_rx_buffer();
- i_counter ^= 0x40;
- total += last_rx_timestamp - last_tx_timestamp;
- }
- Serial.print("R,");
- Serial.print(R);
- Serial.print(",");
- Serial.println(total);
- Serial.flush();
- }
- }
- void loop()
- {
- pre_connection();
- wait_card();
- Serial.println("### card connected");
- reset_card();
- Serial.println("### card ready");
- while (true) {
- Serial.println(">");
- while (Serial.available() == 0) {
- if (!check_card()) {
- Serial.println("### card removed");
- return;
- }
- }
- if (Serial.read() == '\n') {
- command();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement