void mfrc522_init() { mfrc522_reset(); // mfrc522_write(TModeReg, 0x8D); // // mfrc522_write(TPrescalerReg, 0x3E); // mfrc522_write(TReloadReg_1, 30); // mfrc522_write(TReloadReg_2, 0); // Config timer to periodically trigger PCD to check PICC. mfrc522_write(TModeReg, 0x00); // Prescaler is 169, timer tick is 2x169 + 1 = 339 tacts, fq is 13.56Mhz, // so 339 * 1 / 13.56 = 0.000025 = 25us per timer tick. mfrc522_write(TPrescalerReg, 0xa9); // Reload val is 1600. 1600 * 0.000025 (25us) = 40ms. mfrc522_write(TReloadReg_1, 0x6); mfrc522_write(TReloadReg_2, 0x40); mfrc522_write(TxASKReg, 0x40); mfrc522_write(ModeReg, 0x3D); uint8_t byte = mfrc522_read(TxControlReg); if(!(byte & 0x03)) { mfrc522_write(TxControlReg, byte | 0x03); } // Activate IRQ signal. mfrc522_write(ComIEnReg, 1 << RxIEn | TimerIEn); mfrc522_write(DivIEnReg, 1 << IRQPushPull); }
void rc522_irq_prepare() { mfrc522_write(BitFramingReg, 0x07); // TxLastBists = BitFramingReg[2..0] ??? // Clear all interrupts flags. mfrc522_write(ComIrqReg, (uint8_t) ~0x80); uint8_t status = mfrc522_read(Status1Reg); // Start timer. mfrc522_write(ControlReg, 1 << TStartNow); }
extern "C" int main(void) { rc522_pcd_select(RC522_PCD_1); mfrc522_init(); rc522_pcd_select(RC522_PCD_2); mfrc522_init(); enc28j60_init(mac_addr); dhcp_retry_time = RTC_GetCounter() + 1; // Check if timer started. uint8_t status = mfrc522_read(Status1Reg); uint32_t poll_time, dns_time; __enable_irq(); rc522_irq_prepare(); rc522_pcd_select(RC522_PCD_1); rc522_irq_prepare(); // Workers. while (1) { // If DHCPD expired or still not assigng request for new net settings. while (dhcp_status != DHCP_ASSIGNED) { dhcp_poll(); } // If cached tag did request, the even is stored to queue, send it to server // in main thread. tag_event_queue_processor(); if (ticks - poll_time > 600) { poll_time = ticks; tcp_poll(); } if (ticks - dns_time > 600) { dns_time = ticks; //dns_query("com"); } } }
void mfrc522_init() { uint8_t byte; mfrc522_reset(); mfrc522_write(TModeReg, 0x8D); mfrc522_write(TPrescalerReg, 0x3E); mfrc522_write(TReloadReg_1, 30); mfrc522_write(TReloadReg_2, 0); mfrc522_write(TxASKReg, 0x40); mfrc522_write(ModeReg, 0x3D); byte = mfrc522_read(TxControlReg); if(!(byte&0x03)) { mfrc522_write(TxControlReg,byte|0x03); } }
extern "C" void EXTI15_10_IRQHandler() { if (EXTI_GetITStatus(EXTI_Line10) == SET) { rc522_pcd_select(RC522_PCD_1); } else if (EXTI_GetITStatus(EXTI_Line11) == SET) { rc522_pcd_select(RC522_PCD_2); } // Get active interrupts from RC522. uint8_t mfrc522_com_irq_reg = mfrc522_read(ComIrqReg); // If some PICC answered handle it to retrieve additional data from it. if (mfrc522_com_irq_reg & (1 << RxIEn)) { //static uint8_t led_state = 0; // Acknowledge receive irq. mfrc522_write(ComIrqReg, 1 << RxIEn); // Attempt to retrieve tag ID and in case of success check node access. rfid_irq_tag_handler(); rc522_irq_prepare(); } // If it's timer IRQ then request RC522 to start looking for CARD again // and back control to the main thread. else if (mfrc522_com_irq_reg & TimerIEn) { // Down timer irq. mfrc522_write(ComIrqReg, TimerIEn); // As was checked, after Transceive_CMD the FIFO is emptied, so we need put PICC_REQALL // here again, otherwise PICC won't be able response to RC522. mfrc522_write(FIFOLevelReg, mfrc522_read(FIFOLevelReg) | 0x80); // flush FIFO data mfrc522_write(FIFODataReg, PICC_REQALL); // Unfortunately Transceive seems not terminates receive stage automatically in PICC doesn't respond. // so we again need activate command to enter transmitter state to pass PICC_REQALL cmd to PICC // otherwise it won't response due to the ISO 14443 standard. mfrc522_write(CommandReg, Transceive_CMD); // When data and command are correct issue the transmit operation. mfrc522_write(BitFramingReg, mfrc522_read(BitFramingReg) | 0x80); // Start timer. When it will end it again cause this IRQ handler to search the PICC. // Clear STM32 irq bit. if (rc522_select == rc522_1_select) { EXTI_ClearITPendingBit(EXTI_Line10); } else if (rc522_select == rc522_2_select) { EXTI_ClearITPendingBit(EXTI_Line11); } mfrc522_write(ControlReg, 1 << TStartNow); return; } if (rc522_select == rc522_1_select) { EXTI_ClearITPendingBit(EXTI_Line10); } else if (rc522_select == rc522_2_select) { EXTI_ClearITPendingBit(EXTI_Line11); } }
extern "C" void TIM2_IRQHandler() { open_node(); if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(TIM2, TIM_IT_Update); uint8_t pcd = RC522_PCD_1; do { // Chose rfid device. rc522_pcd_select(pcd); uint8_t status = mfrc522_read(Status1Reg); __disable_irq(); // If timer is not running and interrupt timer flag is not active reinit device. if (!(status & TRunning)) { uint8_t need_reinit = 0; switch (pcd) { case RC522_PCD_1: if (EXTI_GetITStatus(EXTI_Line10) == RESET) need_reinit = 1; break; case RC522_PCD_2: if (EXTI_GetITStatus(EXTI_Line11) == RESET) need_reinit = 1; break; } if (need_reinit) { spi_hardware_failure_signal(); mfrc522_init(); __enable_irq(); rc522_irq_prepare(); } } __enable_irq(); } while (pcd++ < RC522_PCD_2); // Check enc28j60 chip and restart if needed. if (!enc28j60_revid || (enc28j60_revid != enc28j60_rcr(EREVID)) || (GPIO_ReadInputDataBit(ETH_GPIO, ETH_IRQ_PIN) == RESET && (EXTI_GetITStatus(EXTI_Line2) == RESET))) { enc28j60_init(mac_addr); } uint16_t phstat1 = enc28j60_read_phy(PHSTAT1); // Если ethernet провод вытаскивали, обновить DHCP. // Пока отключено, т.к. по непонятным причинам LLSTAT падает иногда // хотя коннект сохраняется, что вызывает провалы в доступности интерфейса на 3-10 секунд, // пока интерфейс не поднимится по DHCP заного, однако если согласно LLSTAT линк выключен // но мы не гасим интерфейс он продолжает нормально работать. if(!(phstat1 & PHSTAT1_LLSTAT)) { static uint16_t link_dhcp_time; // Avoid frequently link checks. if (ticks - link_dhcp_time > 5000) { link_dhcp_time = ticks; // Обновим адрес через 5 секунд // (после того, как линк появится) dhcp_status = DHCP_INIT; dhcp_retry_time = RTC_GetCounter() + 2; // Линка нет - опускаем интерфейс ip_addr = 0; ip_mask = 0; ip_gateway = 0; enc28j60_init(mac_addr); } } } }
uint8_t mfrc522_to_card(uint8_t cmd, uint8_t *send_data, uint8_t send_data_len, uint8_t *back_data, uint32_t *back_data_len) { uint8_t status = ERROR; uint8_t irqEn = 0x00; uint8_t waitIRq = 0x00; uint8_t lastBits; uint8_t n; uint8_t tmp; uint32_t i; switch (cmd) { case MFAuthent_CMD: //Certification cards close { irqEn = 0x12; waitIRq = 0x10; break; } case Transceive_CMD: //Transmit FIFO data { irqEn = 0x77; waitIRq = 0x30; break; } default: break; } //mfrc522_write(ComIEnReg, irqEn|0x80); //Interrupt request n=mfrc522_read(ComIrqReg); mfrc522_write(ComIrqReg,n&(~0x80));//clear all interrupt bits n=mfrc522_read(FIFOLevelReg); mfrc522_write(FIFOLevelReg,n|0x80);//flush FIFO data mfrc522_write(CommandReg, Idle_CMD); //NO action; Cancel the current cmd??? //Writing data to the FIFO for (i=0; i<send_data_len; i++) { mfrc522_write(FIFODataReg, send_data[i]); } //Execute the cmd mfrc522_write(CommandReg, cmd); if (cmd == Transceive_CMD) { n=mfrc522_read(BitFramingReg); mfrc522_write(BitFramingReg,n|0x80); } //Waiting to receive data to complete i = 2000; //i according to the clock frequency adjustment, the operator M1 card maximum waiting time 25ms??? do { //CommIrqReg[7..0] //Set1 TxIRq RxIRq IdleIRq HiAlerIRq LoAlertIRq ErrIRq TimerIRq n = mfrc522_read(ComIrqReg); i--; } while ((i!=0) && !(n&0x01) && !(n&waitIRq)); tmp=mfrc522_read(BitFramingReg); mfrc522_write(BitFramingReg,tmp&(~0x80)); if (i != 0) { if(!(mfrc522_read(ErrorReg) & 0x1B)) //BufferOvfl Collerr CRCErr ProtecolErr { status = CARD_FOUND; if (n & irqEn & 0x01) { status = CARD_NOT_FOUND; //?? } if (cmd == Transceive_CMD) { n = mfrc522_read(FIFOLevelReg); lastBits = mfrc522_read(ControlReg) & 0x07; if (lastBits) { *back_data_len = (n-1)*8 + lastBits; } else { *back_data_len = n*8; } if (n == 0) { n = 1; } if (n > MAX_LEN) { n = MAX_LEN; } //Reading the received data in FIFO for (i=0; i<n; i++) { back_data[i] = mfrc522_read(FIFODataReg); } } } else { status = ERROR; } } //SetBitMask(ControlReg,0x80); //timer stops //mfrc522_write(cmdReg, PCD_IDLE); return status; }
int main() { DDRC &= ~(1<<PC0); //input for DPDT switch increase_day_count_eeprom(); //some more initialization of EEPROM /*** Students list ***/ /** These are the bytes that are read from the RFID tags of the students**/ uint8_t person_byte[MAX_PEOPLE][5] = { {0x23, 0x6D, 0xD6, 0x00, 0x98} , {0xF9, 0x46, 0x1D, 0x00, 0xA2}, {0xA3, 0x7E, 0x30, 0x02, 0xEF} }; //Some tags that we used to experiment //{0xF9, 0x46, 0x1D, 0x00, 0xA2} //{0x23, 0x6D, 0xD6, 0x00, 0x98} - recognized1 //{0xF9, 0x46, 0x1D, 0x00, 0xA2} - recognized2 (change any bit in any of these 2 to see effect of unrecognized person entering) //{0xA3, 0x7E, 0x30, 0x02, 0xEF} - Nimi - white //{0x5B, 0xA8, 0x2C, 0x00, 0xDF} - Adnan - blue // person name list .. these used to control people names etc int detected_person; int person_entry_list[MAX_PEOPLE] = {0, 0, 0}; char *person_name[MAX_LEN] = { (char *)"Sibat", (char *)"Ripon" , (char *)"Nimi" }; char *entered_msg = (char *)" entered"; char *left_msg = (char *)" left"; char msg_to_show[100]; int person_count = 0; // iterator and byte array to use later uint8_t byte, i; uint8_t str[MAX_LEN]; _delay_ms(50); // initialize the LCD LCDInit(LS_BLINK); LCDWriteStringXY(2,0,"RFID Reader"); // spi initialization spi_init(); _delay_ms(1000); LCDClear(); //init reader mfrc522_init(); // poll until reader is found while(1) { byte = mfrc522_read(VersionReg); if(byte == 0x92) { LCDClear(); LCDWriteStringXY(2,0,"Detected"); _delay_ms(1000); break; } else { LCDClear(); LCDWriteStringXY(0,0,"No reader found"); _delay_ms(800); LCDClear(); LCDWriteStringXY(0, 0, "Connect reader"); _delay_ms(1000); } } // ready to run _delay_ms(1500); LCDClear(); // initializing the RGB LEDs DDRA = 0xFF; PORTA = 0xFE; //Interrupt INT2 DDRB |= (1<<PB2); // Set PB2 as input (Using for interrupt INT2) PORTB |= (1<<PB2); // Enable PB2 pull-up resistor // setting up the timer codes // setting up the LED animation initials // TODO timer code ... START HERE ... TCCR1A = 0x00; TCCR1B = 0x01; TIMSK = 0x04; min = 0; sec = 0; hour = 0; sec_counter = 0; LED_animation_status = 0; LED_animation_on = 1; program_status_2_first_time = 1; program_status_3_first_time = 1; program_status_4_first_time = 1; // TODO timer code ... ENDS HERE ... // The loop starts here // program status : 1 means entrance period // : 2 means session period // : 3 means session ended program_status = 1; //Using interrupt 2 for reading history mode GICR &= ~(1<<INT2); // Disable INT2 MCUCSR |= (1<<ISC2); // Trigger INT2 on 1 = rising edge , 0 falling edge GIFR |= (1<<INTF2); // clear INTF2 GICR |= (1<<INT2); // Enable INT2 sei(); while(1) { spi_init(); mfrc522_init(); byte = mfrc522_read(ComIEnReg); mfrc522_write(ComIEnReg,byte|0x20); byte = mfrc522_read(DivIEnReg); mfrc522_write(DivIEnReg,byte|0x80); if(program_status == 1) { LCDClear(); LCDWriteStringXY(0, 0, "Show your card."); LCDWriteStringXY(0, 1, "#students:"); LCDWriteIntXY(12,1, person_count ,2 ); byte = mfrc522_request(PICC_REQALL,str); if(byte == CARD_FOUND) { byte = mfrc522_get_card_serial(str); if(byte == CARD_FOUND) { LED_animation_on = 0; // check for person 1 detected_person = -1; for(i = 0; i < MAX_PEOPLE; i++) { for(byte = 0; byte < 5; byte++) { /***The following piece of code was written to test and read the bytes off the tags and print them***/ //LCDClear(); //LCDWriteIntXY(0,0,byte,2); //LCDWriteIntXY(0,1,str[byte],14); //_delay_ms(3000); if(str[byte] != person_byte[i][byte]) { break; } } if(byte == 5) { detected_person = i; break; } } if(i == MAX_PEOPLE) { detected_person = -1; } // showing message on LCD upon decision of the person LCDClear(); if(detected_person == -1) { PORTA = 0x7E; LCDClear(); LCDWriteStringXY(0, 0, "Access denied!"); _delay_ms(2000); PORTA = 0xFE; LCDClear(); LCDWriteStringXY(0, 0, "Unrecognized!"); } else { PORTA = 0xFD; LCDClear(); LCDWriteStringXY(0, 0, "Access granted!"); _delay_ms(2000); if(person_entry_list[i] == 0) { person_entry_list[i] = 1; } else { person_entry_list[i] = 0; } strcpy(msg_to_show, person_name[detected_person]); if(person_entry_list[i] == 0) { /** Code to sound buzzer when a student is leaving **/ PORTA = 0x7D; _delay_ms(200); PORTA = 0xFD; // end of buzzer code //EEPROM WRITE if(write_enable_eeprom == 1){ eeprom_update_byte ((uint8_t*) (&NonVolatileIsPresent[curr_day][i]), 0); } person_count--; strcat(msg_to_show, left_msg); } else { /** Code to sound buzzer when a student is entering **/ PORTA = 0x7D; _delay_ms(200); PORTA = 0xFD; _delay_ms(100); PORTA = 0x7D; _delay_ms(200); PORTA = 0xFD; // end of buzzer code //EEPROM WRITE if(write_enable_eeprom == 1) { eeprom_write_byte ((uint8_t*) (&NonVolatileIsPresent[curr_day][i]), 1); eeprom_update_byte ((uint8_t*) (&NonVolatileHour[curr_day][i]), hour); eeprom_update_byte ((uint8_t*) (&NonVolatileMinute[curr_day][i]), min); eeprom_update_byte ((uint8_t*) (&NonVolatileSecond[curr_day][i]), sec); } person_count++; strcat(msg_to_show, entered_msg); } LCDClear(); LCDWriteStringXY(0, 0, msg_to_show); } _delay_ms(3000); PORTA = 0xFE; LCDClear(); LED_animation_on = 1; } else { LCDClear(); LCDWriteStringXY(0,1,"Error"); } } _delay_ms(200); } else if(program_status == 2) { LCDClear(); LCDWriteStringXY(0, 0, "In session now!"); LCDWriteStringXY(0, 1, "#students:"); LCDWriteIntXY(12,1, person_count ,2 ); byte = mfrc522_request(PICC_REQALL,str); if(byte == CARD_FOUND) { LED_animation_on = 0; PORTA = 0x7E; LCDClear(); LCDWriteStringXY(0, 0, "Warning!!"); _delay_ms(2000); LCDClear(); LCDWriteStringXY(0, 0, "Session running."); _delay_ms(2000); PORTA = 0xFE; LCDClear(); LCDWriteStringXY(0, 0, "Can't go out/in."); _delay_ms(2000); LCDClear(); PORTA = 0xFB; LED_animation_on = 1; } _delay_ms(200); } else if(program_status == 3) { LCDClear(); LCDWriteStringXY(0, 0, "Session ended!"); LCDWriteStringXY(0, 1, "#students:"); LCDWriteIntXY(12,1, person_count ,2 ); byte = mfrc522_request(PICC_REQALL,str); if(byte == CARD_FOUND) { byte = mfrc522_get_card_serial(str); if(byte == CARD_FOUND) { LED_animation_on = 0; // check for person 1 detected_person = -1; for(i = 0; i < MAX_PEOPLE; i++) { for(byte = 0; byte < 5; byte++) { if(str[byte] != person_byte[i][byte]) { break; } } if(byte == 5) { detected_person = i; break; } } // showing message on LCD upon decision of the person if(detected_person == -1) { PORTA = 0x7E; LCDClear(); LCDWriteStringXY(0, 0, "Unrecognized!"); _delay_ms(2000); PORTA = 0xFE; } else { PORTA = 0xFB; if(person_entry_list[detected_person] != 0){ LCDClear(); strcpy(msg_to_show, "Take care "); strcat(msg_to_show, person_name[detected_person]); LCDWriteStringXY(0, 0, msg_to_show); _delay_ms(1000); LCDClear(); strcpy(msg_to_show, person_name[detected_person]); strcat(msg_to_show, left_msg); LCDWriteStringXY(0, 0, msg_to_show); person_entry_list[detected_person] = 0; person_count--; //unnecessary sanity check if(person_count == 0) { break; } } } _delay_ms(3000); PORTA = 0xFD; LCDClear(); LED_animation_on = 1; } else { PORTA = 0x7E; LCDClear(); LCDWriteStringXY(0,1,"Error"); _delay_ms(2000); PORTA = 0xFE; LCDClear(); PORTA = 0xFD; } } _delay_ms(200); } else { /***This is the warning phase. When leaving period has ended, but some students were still stuck in the classroom, the buzzer buzzes off continuously suspecting that some students might be sick or in trouble. ***/ if(person_count != 0) { LED_animation_on = 0; PORTA = 0x7E; LCDClear(); LCDWriteIntXY(0,0, person_count ,2 ); LCDWriteStringXY(3, 0, "student could"); LCDWriteStringXY(0, 1, "not get out"); _delay_ms(1500); LCDClear(); LCDWriteStringXY(0, 0, "Take caution!"); _delay_ms(1500); PORTA = 0xFE; _delay_ms(400); } else { /**When all students have left, nothing to do. **/ LCDClear(); break; } } } LED_animation_on = 1; PORTA = 0xFB; temp_PORTA = PORTA; LCDClear(); LCDWriteStringXY(0, 0, "Everyone left."); while(1) { ; } cli(); }