Skip to content
Snippets Groups Projects
Commit 602402b8 authored by jjunohj's avatar jjunohj
Browse files

Add RPI 1

parent 34b795e5
No related branches found
No related tags found
No related merge requests found
.DS_Store 0 → 100644
File added
# Smart_Library
## 전체 구조도
<img width="1285" alt="스크린샷 2023-06-22 오후 3 23 21" src="https://github.com/jjunohj/MCU-JS/assets/121740394/0bd5fe49-1a69-4c91-9ea8-2fdb693ca08f">
## Getting started
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
## Add your files
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
### RPI 1 (도서관 중앙부)
```
cd existing_repo
git remote add origin https://git.ajou.ac.kr/sys_programming_seven/smart_library.git
git branch -M main
git push -uf origin main
rfid.c 내부의 server_address[], port를 도서관 개폐부와 연결
make run
```
## Integrate with your tools
- [ ] [Set up project integrations](https://git.ajou.ac.kr/sys_programming_seven/smart_library/-/settings/integrations)
## Collaborate with your team
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
- [ ] [Automatically merge when pipeline succeeds](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
## Test and Deploy
Use the built-in continuous integration in GitLab.
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing(SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
***
# Editing this README
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thank you to [makeareadme.com](https://www.makeareadme.com/) for this template.
## Suggestions for a good README
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
## Name
Choose a self-explaining name for your project.
## Description
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
## Badges
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
## Visuals
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
## Installation
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
## Usage
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
## Support
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
## Roadmap
If you have ideas for releases in the future, it is a good idea to list them in the README.
## Contributing
State if you are open to contributions and what your requirements are for accepting them.
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
## Authors and acknowledgment
Show your appreciation to those who have contributed to the project.
## License
For open source projects, say how it is licensed.
## Project status
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
VPATH = _build
objects = rfid.o RC522.o
.PHONY : clear run
top:
make clear
make compile
compile: $(objects)
gcc $(objects) -o rfid -lwiringPi
clear:
rm -f rfid
rm -f $(objects)
run: clear compile
./rfid
./$(VPATH)/rfid.o:RC522.o
gcc -c rfid.c
./$(VPATH)/RCC522.o:
gcc -c RC522.c RC522.h
#include <wiringPi.h>
#include <wiringPiSPI.h>
#include <stdio.h>
#include <string.h>
#include "RC522.h"
uint8_t rst_pin;
void RC522_setup(uint8_t rst) {
rst_pin = rst;
wiringPiSetup();
pinMode(rst_pin, OUTPUT);
digitalWrite(rst_pin, 1);
wiringPiSPISetup(0, 100000);
}
void RC522_RST(uint8_t v) {
digitalWrite(rst_pin, v);
}
/**
* @brief Reads an RC522 register
* @param ucAddress, register address
* @retval Current value of the register
*/
uint8_t ReadRawRC(uint8_t ucAddress) {
static uint8_t _buf1[0x2];
uint8_t ucAddr, ucReturn;
ucAddr = ((ucAddress << 1) & 0x7E) | 0x80;
_buf1[0] = ucAddr;
wiringPiSPIDataRW(0, _buf1, 2);
ucReturn = _buf1[1];
return ucReturn;
}
/**
* @brief Writes to an RC522 register
* @param ucAddress, register address
* @param ucValue, value to write to the register
* @retval None
*/
void WriteRawRC(uint8_t ucAddress, uint8_t ucValue) {
static uint8_t _buf1[0x2];
uint8_t ucAddr;
ucAddr = (ucAddress << 1) & 0x7E;
_buf1[0] = ucAddr;
_buf1[1] = ucValue;
wiringPiSPIDataRW(0, _buf1, 2);
}
/**
* @brief Sets a bit in an RC522 register
* @param ucReg, register address
* @param ucMask, bit value to set
* @retval None
*/
void SetBitMask(uint8_t ucReg, uint8_t ucMask) {
uint8_t ucTemp;
ucTemp = ReadRawRC(ucReg);
WriteRawRC(ucReg, ucTemp | ucMask); // set bit mask
}
/**
* @brief Clears a bit in an RC522 register
* @param ucReg, register address
* @param ucMask, bit value to clear
* @retval None
*/
void ClearBitMask(uint8_t ucReg, uint8_t ucMask) {
uint8_t ucTemp;
ucTemp = ReadRawRC(ucReg);
WriteRawRC(ucReg, ucTemp & (~ucMask)); // clear bit mask
}
/**
* @brief Turns on the antenna of the RC522
* @param None
* @retval None
*/
void PcdAntennaOn(void) {
uint8_t uc;
uc = ReadRawRC(TxControlReg);
if (!(uc & 0x03)) {
SetBitMask(TxControlReg, 0x03);
}
}
/**
* @brief Turns off the antenna of the RC522
* @param None
* @retval None
*/
void PcdAntennaOff(void) {
ClearBitMask(TxControlReg, 0x03);
}
/**
* @brief Resets the RC522
* @param None
* @retval None
*/
void PcdReset(void) {
RC522_RST(1);
delayMicroseconds(1);
RC522_RST(0);
delayMicroseconds(1);
RC522_RST(1);
delayMicroseconds(1);
WriteRawRC(CommandReg, 0x0F);
while (ReadRawRC(CommandReg) & 0x10);
delayMicroseconds(1);
//Configures commonly used modes for sending and receiving and communication with Mifare cards, initializes CRC value to 0x6363
WriteRawRC(ModeReg, 0x3D);
WriteRawRC(TReloadRegL, 30); // Low 16 bits of the 16- bit timer
WriteRawRC(TReloadRegH, 0); // High 16 bits of the 16-bit timer
WriteRawRC(TModeReg, 0x8D); // Defines settings for internal timer
WriteRawRC(TPrescalerReg, 0x3E); // Sets the timer's prescaler coefficient
WriteRawRC(TxAutoReg, 0x40); // Modulates the transmitted signal 100% ASK
}
/**
* @brief Sets the operating mode of the RC522
* @param ucType, operating mode
* @retval None
*/
void M500PcdConfigISOType(uint8_t ucType) {
if (ucType == 'A') { //ISO14443_A
ClearBitMask(Status2Reg, 0x08);
WriteRawRC(ModeReg, 0x3D); //3F
WriteRawRC(RxSelReg, 0x86); //84
WriteRawRC(RFCfgReg, 0x7F); //4F
WriteRawRC(TReloadRegL, 30);
WriteRawRC(TReloadRegH, 0);
WriteRawRC(TModeReg, 0x8D);
WriteRawRC(TPrescalerReg, 0x3E);
delayMicroseconds(2);
PcdAntennaOn(); //Open antenna
}
}
/**
* @brief Communicates with an ISO14443 card using RC522
* @param ucCommand, RC522 command word
* @param pInData, data to send to the card through RC522
* @param ucInLenByte, byte length of the data to send
* @param pOutData, returned data from the card
* @param pOutLenBit, bit length of the returned data
* @retval Status value = MI_OK, success
*/
char PcdComMF522(uint8_t ucCommand, uint8_t* pInData, uint8_t ucInLenByte, uint8_t* pOutData, uint32_t* pOutLenBit)
{
char cStatus = MI_ERR;
uint8_t ucIrqEn = 0x00;
uint8_t ucWaitFor = 0x00;
uint8_t ucLastBits;
uint8_t ucN;
uint32_t ul;
switch (ucCommand) {
case PCD_AUTHENT:
ucIrqEn = 0x12;
ucWaitFor = 0x10;
break;
case PCD_TRANSCEIVE:
ucIrqEn = 0x77;
ucWaitFor = 0x30;
break;
default:
break;
}
WriteRawRC(ComIEnReg, ucIrqEn | 0x80);
ClearBitMask(ComIrqReg, 0x80);
WriteRawRC(CommandReg, PCD_IDLE);
SetBitMask(FIFOLevelReg, 0x80);
for (ul = 0; ul < ucInLenByte; ul++) {
WriteRawRC(FIFODataReg, pInData[ul]);
}
WriteRawRC(CommandReg, ucCommand);
if (ucCommand == PCD_TRANSCEIVE) {
SetBitMask(BitFramingReg, 0x80);
}
ul = 1000;
do {
ucN = ReadRawRC(ComIrqReg);
ul--;
} while ((ul != 0) && (!(ucN & 0x01)) && (!(ucN & ucWaitFor)));
ClearBitMask(BitFramingReg, 0x80);
if (ul != 0) {
if (!(ReadRawRC(ErrorReg) & 0x1B)) {
cStatus = MI_OK;
if (ucN & ucIrqEn & 0x01) {
cStatus = MI_NOTAGERR;
}
if (ucCommand == PCD_TRANSCEIVE) {
ucN = ReadRawRC(FIFOLevelReg);
ucLastBits = ReadRawRC(ControlReg) & 0x07;
if (ucLastBits) {
*pOutLenBit = (ucN - 1) * 8 + ucLastBits;
} else {
*pOutLenBit = ucN * 8;
}
if (ucN == 0) {
ucN = 1;
}
if (ucN > MAXRLEN) {
ucN = MAXRLEN;
}
for (ul = 0; ul < ucN; ul++) {
pOutData[ul] = ReadRawRC(FIFODataReg);
}
}
} else {
cStatus = MI_ERR;
}
}
SetBitMask(ControlReg, 0x80);
WriteRawRC(CommandReg, PCD_IDLE);
return cStatus;
}
char PcdRequest(uint8_t ucReq_code, uint8_t* pTagType) { //Request cards, read card type number
char cStatus;
uint8_t ucComMF522Buf[MAXRLEN];
uint32_t ulLen;
ClearBitMask(Status2Reg, 0x08);
WriteRawRC(BitFramingReg, 0x07);
SetBitMask(TxControlReg, 0x03);
ucComMF522Buf[0] = ucReq_code;
cStatus = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 1, ucComMF522Buf, &ulLen);
if ((cStatus == MI_OK) && (ulLen == 0x10)) {
* pTagType = ucComMF522Buf[0];
*(pTagType+1) = ucComMF522Buf[1];
} else {
cStatus = MI_ERR;
}
return cStatus;
}
char PcdAnticoll(uint8_t* pSnr ){ //Anti-collision detection, reading selected card serial number card
char cStatus;
uint8_t uc, ucSnr_check = 0;
uint8_t ucComMF522Buf[MAXRLEN];
uint32_t ulLen;
ClearBitMask(Status2Reg, 0x08);
WriteRawRC(BitFramingReg, 0x00);
ClearBitMask(CollReg, 0x80);
ucComMF522Buf[0] = 0x93;
ucComMF522Buf[1] = 0x20;
cStatus = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 2, ucComMF522Buf, &ulLen);
if (cStatus == MI_OK) {
for (uc = 0; uc < 4; uc++) {
*(pSnr + uc) = ucComMF522Buf[uc];
ucSnr_check ^= ucComMF522Buf[uc];
}
if (ucSnr_check != ucComMF522Buf[uc]) {
cStatus = MI_ERR;
}
}
SetBitMask(CollReg, 0x80);
return cStatus;
}
void CalulateCRC(uint8_t* pIndata, uint8_t ucLen, uint8_t* pOutData) {
uint8_t uc, ucN;
ClearBitMask(DivIrqReg, 0x04);
WriteRawRC(CommandReg, PCD_IDLE);
SetBitMask(FIFOLevelReg, 0x80);
for (uc = 0; uc < ucLen; uc++) {
WriteRawRC(FIFODataReg, *(pIndata+uc));
}
WriteRawRC(CommandReg, PCD_CALCCRC);
uc = 0xFF;
do {
ucN = ReadRawRC(DivIrqReg);
uc--;
} while ((uc != 0) && !(ucN & 0x04));
pOutData[0] = ReadRawRC(CRCResultRegL);
pOutData[1] = ReadRawRC(CRCResultRegM);
}
char PcdSelect(uint8_t* pSnr) {
char ucN;
uint8_t uc, ucComMF522Buf[MAXRLEN];
uint32_t ulLen;
ucComMF522Buf[0] = PICC_ANTICOLL1;
ucComMF522Buf[1] = 0x70;
ucComMF522Buf[6] = 0;
for (uc = 0; uc < 4; uc++) {
ucComMF522Buf[uc+2] = *(pSnr+uc);
ucComMF522Buf[6] ^= *(pSnr+uc);
}
CalulateCRC(ucComMF522Buf, 7, &ucComMF522Buf[7]);
ClearBitMask(Status2Reg, 0x08);
ucN = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 9, ucComMF522Buf, &ulLen);
if ((ucN == MI_OK) && (ulLen == 0x18)) {
ucN = MI_OK;
} else {
ucN = MI_ERR;
}
return ucN;
}
char PcdAuthState(uint8_t ucAuth_mode, uint8_t ucAddr, uint8_t* pKey, uint8_t* pSnr) {
char cStatus;
uint8_t uc, ucComMF522Buf[MAXRLEN];
uint32_t ulLen;
ucComMF522Buf[0] = ucAuth_mode;
ucComMF522Buf[1] = ucAddr;
for (uc = 0; uc < 6; uc++) {
ucComMF522Buf[uc+2] = *(pKey+uc);
}
for (uc = 0; uc < 6; uc++) {
ucComMF522Buf[uc+8] = *(pSnr+uc);
}
cStatus = PcdComMF522(PCD_AUTHENT, ucComMF522Buf, 12, ucComMF522Buf, &ulLen);
if ((cStatus != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08))) {
cStatus = MI_ERR;
}
return cStatus;
}
char PcdWrite(uint8_t ucAddr, uint8_t* pData) { // Write block data
char cStatus;
uint8_t uc, ucComMF522Buf[MAXRLEN];
uint32_t ulLen;
ucComMF522Buf[0] = PICC_WRITE;
ucComMF522Buf[1] = ucAddr;
CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);
cStatus = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &ulLen);
if ((cStatus == MI_OK) && (ulLen == 4) && ((ucComMF522Buf[0] & 0x0F) == 0x0A)) {
for (uc = 0; uc < 16; uc++) {
ucComMF522Buf[uc] = *(pData+uc);
}
CalulateCRC(ucComMF522Buf, 16, &ucComMF522Buf[16]);
cStatus = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 18, ucComMF522Buf, &ulLen);
if ((cStatus != MI_OK) || (ulLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A)) {
cStatus = MI_ERR;
}
} else {
cStatus = MI_ERR;
}
return cStatus;
}
char PcdRead(uint8_t ucAddr, uint8_t* pData) { // Read block data
char cStatus;
uint8_t uc, ucComMF522Buf[MAXRLEN];
uint32_t ulLen;
ucComMF522Buf[0] = PICC_READ;
ucComMF522Buf[1] = ucAddr;
CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);
cStatus = PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &ulLen);
if ((cStatus == MI_OK) && (ulLen == 0x90)) {
for (uc = 0; uc < 16; uc++) {
*(pData + uc) = ucComMF522Buf[uc];
}
} else {
cStatus = MI_ERR;
}
return cStatus;
}
char PcdHalt() { // Command the cards into sleep mode
uint8_t ucComMF522Buf[MAXRLEN];
uint32_t ulLen;
ucComMF522Buf[0] = PICC_HALT;
ucComMF522Buf[1] = 0;
CalulateCRC(ucComMF522Buf, 2, &ucComMF522Buf[2]);
PcdComMF522(PCD_TRANSCEIVE, ucComMF522Buf, 4, ucComMF522Buf, &ulLen);
return MI_OK;
}
void IC_CMT(uint8_t* UID, uint8_t* KEY, uint8_t RW, uint8_t* Dat) { // IC Card Communication
uint8_t ucArray_ID[4] = {0};
PcdRequest(0x52, ucArray_ID);
PcdAnticoll(ucArray_ID);
PcdSelect(UID);
PcdAuthState(0x60, 0x10, KEY, UID);
if (RW) {
PcdRead(0x10, Dat);
} else {
PcdWrite(0x10, Dat);
}
PcdHalt();
}
#ifndef __RC522_CONFIG_H
#define __RC522_CONFIG_H
/////////////////////////////////////////////////////////////////////
//MF522 Command word
/////////////////////////////////////////////////////////////////////
#define PCD_IDLE 0x00 //현재 명령 취소
#define PCD_AUTHENT 0x0E //인증 키
#define PCD_RECEIVE 0x08 //데이터 수신
#define PCD_TRANSMIT 0x04 //데이터 전송
#define PCD_TRANSCEIVE 0x0C //데이터 전송 및 수신
#define PCD_RESETPHASE 0x0F //재설정
#define PCD_CALCCRC 0x03 //CRC 계산
/////////////////////////////////////////////////////////////////////
//Mifare_One 카드 Command word
/////////////////////////////////////////////////////////////////////
#define PICC_REQIDL 0x26 //수신기간 내에 대기중인 카드 대기열 찾기
#define PICC_REQALL 0x52 // 수신기 안에 있는 모든 카드 찾기
#define PICC_ANTICOLL1 0x93 //충돌 방지
#define PICC_ANTICOLL2 0x95
#define PICC_AUTHENT1A 0x60 //A키 검증
#define PICC_AUTHENT1B 0x61 //B키 검증
#define PICC_READ 0x30 //블록 읽기
#define PICC_WRITE 0xA0 //블록 쓰기
#define PICC_DECREMENT 0xC0 //차감
#define PICC_INCREMENT 0xC1 //충전
#define PICC_RESTORE 0xC2 //블록 데이터를 버퍼로 복원
#define PICC_TRANSFER 0xB0 //버퍼에 있는 데이터 보관
#define PICC_HALT 0x50 //카드 비활성화
/////////////////////////////////////////////////////////////////////
//MF522 FIFO 길이 정의
/////////////////////////////////////////////////////////////////////
#define DEF_FIFO_LENGTH 64 //FIFO 크기 = 64바이트
#define MAXRLEN 18
/////////////////////////////////////////////////////////////////////
//MF522 레지스터 정의
/////////////////////////////////////////////////////////////////////
// PAGE 0
#define RFU00 0x00
#define CommandReg 0x01
#define ComIEnReg 0x02
#define DivlEnReg 0x03
#define ComIrqReg 0x04
#define DivIrqReg 0x05
#define ErrorReg 0x06
#define Status1Reg 0x07
#define Status2Reg 0x08
#define FIFODataReg 0x09
#define FIFOLevelReg 0x0A
#define WaterLevelReg 0x0B
#define ControlReg 0x0C
#define BitFramingReg 0x0D
#define CollReg 0x0E
#define RFU0F 0x0F
// PAGE 1
#define RFU10 0x10
#define ModeReg 0x11
#define TxModeReg 0x12
#define RxModeReg 0x13
#define TxControlReg 0x14
#define TxAutoReg 0x15
#define TxSelReg 0x16
#define RxSelReg 0x17
#define RxThresholdReg 0x18
#define DemodReg 0x19
#define RFU1A 0x1A
#define RFU1B 0x1B
#define MifareReg 0x1C
#define RFU1D 0x1D
#define RFU1E 0x1E
#define SerialSpeedReg 0x1F
// PAGE 2
#define RFU20 0x20
#define CRCResultRegM 0x21
#define CRCResultRegL 0x22
#define RFU23 0x23
#define ModWidthReg 0x24
#define RFU25 0x25
#define RFCfgReg 0x26
#define GsNReg 0x27
#define CWGsCfgReg 0x28
#define ModGsCfgReg 0x29
#define TModeReg 0x2A
#define TPrescalerReg 0x2B
#define TReloadRegH 0x2C
#define TReloadRegL 0x2D
#define TCounterValueRegH 0x2E
#define TCounterValueRegL 0x2F
// PAGE 3
#define RFU30 0x30
#define TestSel1Reg 0x31
#define TestSel2Reg 0x32
#define TestPinEnReg 0x33
#define TestPinValueReg 0x34
#define TestBusReg 0x35
#define AutoTestReg 0x36
#define VersionReg 0x37
#define AnalogTestReg 0x38
#define TestDAC1Reg 0x39
#define TestDAC2Reg 0x3A
#define TestADCReg 0x3B
#define RFU3C 0x3C
#define RFU3D 0x3D
#define RFU3E 0x3E
#define RFU3F 0x3F
/////////////////////////////////////////////////////////////////////
//MF522 통신 에러 코드
/////////////////////////////////////////////////////////////////////
#define MI_OK 0x26
#define MI_NOTAGERR 0xcc
#define MI_ERR 0xbb
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
void RC522_setup(uint8_t rst);
void PcdReset ( void );
void M500PcdConfigISOType ( uint8_t type );
char PcdRequest ( uint8_t req_code, uint8_t* pTagType );
char PcdAnticoll ( uint8_t* pSnr);
char PcdHalt ( void );
char PcdSelect ( uint8_t* pSnr );
void CalulateCRC ( uint8_t* pIndata, uint8_t len, uint8_t* pOutData );
char PcdAuthState ( uint8_t auth_mode, uint8_t addr, uint8_t* pKey, uint8_t* pSnr );
char PcdRead ( uint8_t addr, uint8_t* pData );
char PcdWrite ( uint8_t addr, uint8_t* pData );
char PcdValue ( uint8_t dd_mode, uint8_t addr, uint8_t* pValue );
char PcdBakValue ( uint8_t sourceaddr, uint8_t goaladdr );
char PcdComMF522 ( uint8_t Command, uint8_t* pInData, uint8_t InLenByte, uint8_t* pOutData, uint32_t* pOutLenBit );
#endif
\ No newline at end of file
File added
# Smart Library
## RFID-RC522
## LCD 1602
```
make run
```
RPI1/rfid 0 → 100755
File added
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdint.h>
#include <wiringPi.h>
#include <wiringPiSPI.h>
#include <wiringPiI2C.h>
#include <stdbool.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "RC522.h"
#define LCD_ADDR 0x27
#define ONE_DAY 86400
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
typedef struct {
char memberId[10];
int borrowed_book;
time_t borrowed_time;
} Member;
int fd;
int BLEN=1;
void write_word(int data){
int temp = data;
if ( BLEN == 1 )
temp |= 0x08;
else
temp &= 0xF7;
wiringPiI2CWrite(fd, temp);
}
void send_command(int comm){
int buf;
// Send bit7-4 firstly
buf = comm & 0xF0;
buf |= 0x04; // RS = 0, RW = 0, EN = 1
write_word(buf);
delay(2);
buf &= 0xFB; // Make EN = 0
write_word(buf);
// Send bit3-0 secondly
buf = (comm & 0x0F) << 4;
buf |= 0x04; // RS = 0, RW = 0, EN = 1
write_word(buf);
delay(2);
buf &= 0xFB; // Make EN = 0
write_word(buf);
}
void send_data(int data){
int buf;
// Send bit7-4 firstly
buf = data & 0xF0;
buf |= 0x05; // RS = 1, RW = 0, EN = 1
write_word(buf);
delay(2);
buf &= 0xFB; // Make EN = 0
write_word(buf);
// Send bit3-0 secondly
buf = (data & 0x0F) << 4;
buf |= 0x05; // RS = 1, RW = 0, EN = 1
write_word(buf);
delay(2);
buf &= 0xFB; // Make EN = 0
write_word(buf);
}
void init(){
send_command(0x33); // Must initialize to 8-line mode at first
delay(5);
send_command(0x32); // Then initialize to 4-line mode
delay(5);
send_command(0x28); // 2 Lines & 5*7 dots
delay(5);
send_command(0x0C); // Enable display without cursor
delay(5);
send_command(0x01); // Clear Screen
wiringPiI2CWrite(fd, 0x08);
}
void clear(){
send_command(0x01); //clear Screen
}
void write_lcd(int x, int y, char data[]){
int addr, i;
int tmp;
if (x < 0) x = 0;
if (x > 15) x = 15;
if (y < 0) y = 0;
if (y > 1) y = 1;
// Move cursor
addr = 0x80 + 0x40 * y + x;
send_command(addr);
tmp = strlen(data);
for (i = 0; i < tmp; i++){
send_data(data[i]);
}
}
int find_member(Member members[], size_t n_members, const char *id) {
for (int i = 0; i < n_members; i++) {
if (strcmp(members[i].memberId, id) == 0) {
return (int)i;
}
}
return -1;
}
const char* readRFID ( void )
{
char cStr [ 30 ];
static uint8_t ucArray_ID [ 4 ]; // 카드 ID
uint8_t ucStatusReturn; // 카드 검색 상태
while ( 1 ) { // 무한 카드 검색
/* PICC_REQALL : 모든 종류의 카드 검색 */
if (( ucStatusReturn = PcdRequest ( PICC_REQALL, ucArray_ID )) != MI_OK ) { // 실패할 경우 다시 카드 검색
ucStatusReturn = PcdRequest ( PICC_REQALL, ucArray_ID );
}
if (ucStatusReturn == MI_OK) { // 카드 검색 성공
if (PcdAnticoll ( ucArray_ID ) == MI_OK) { // 카드 인식 성공
return ucArray_ID;
}
}
}
}
int main(void) {
char server_address[] = "192.168.0.7";
int port = 8888;
Member members[10];
size_t n_members = 0;
int available_books[] = { 1, 1, 1, 1, 1, 1, 1, 1 };
int n_available_books = ARRAY_SIZE(available_books);
int select_num;
char block_num[2];
int sock;
struct sockaddr_in serv_addr;
RC522_setup(7); // Pin : 7
PcdReset(); // RC522 초기화
M500PcdConfigISOType('A'); // ISO14443A 타입으로 설정
fd = wiringPiI2CSetup(LCD_ADDR);
init();
// sock = socket(PF_INET, SOCK_STREAM, 0);
// if (sock == -1) {
// printf("🚫 소켓 생성 실패\r\n");
// exit(1);
// }
// memset(&serv_addr, 0, sizeof(serv_addr));
// serv_addr.sin_family = AF_INET;
// serv_addr.sin_addr.s_addr = inet_addr(server_address);
// serv_addr.sin_port = htons(port);
// if (connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) {
// printf("🚫 서버 연결 실패\r\n");
// exit(1);
// }
while(1) {
printf("\n");
printf("📚 스마트 도서관에 오신 것을 환영합니다 !\n");
printf("😃 회원증을 인식해주세요. . .\r\n");
clear();
write_lcd(0, 0, "Welcome to ");
write_lcd(0, 1, "Smart Library ! ");
delay(2000);
clear();
write_lcd(0, 0, "Please scan your");
write_lcd(0, 1, "membership card");
// 회원번호 출력
const char* id = readRFID();
int member_index = find_member(members, n_members, id);
if (member_index == -1) {
printf("🚫 등록되지 않은 회원입니다.\r\n");
clear();
write_lcd(0, 0, "You are not a ");
write_lcd(0, 1, "member. ");
delay(1000);
write_lcd(0, 0, "Do you wanna ");
write_lcd(0, 1, "sign up? Y:1 N:2");
printf("📝 회원 가입을 하시겠습니까?.\r\n");
printf("1. 예 2. 아니오\r\n");
scanf("%d", &select_num);
if (select_num == 1) {
printf("✅ 회원 가입이 완료되었습니다.\r\n");
clear();
write_lcd(0, 0, "Sign up complete");
strcpy(members[n_members].memberId, id); // 회원번호 저장
members[n_members].borrowed_book = 0;
members[n_members].borrowed_time = 0;
n_members++;
delay(3000);
clear();
} else {
printf("😃 이용해주셔서 감사합니다.\r\n");
clear();
write_lcd(0, 0, "Thank you for ");
write_lcd(0, 1, "using. ");
delay(3000);
clear();
}
continue;
}
else if (member_index >= 0) {
printf("😃 환영합니다 !!\r\n");
clear();
write_lcd(0, 0, "Welcome !! ");
delay(1000);
clear();
printf("--------------------------------\r\n");
printf("ℹ️ 회원번호 : %02X%02X%02X%02X\r\n", id[0], id[1], id[2], id[3]);
if (members[member_index].borrowed_book != 0) {
printf("ℹ️ 대여 중인 도서는 %d번 도서입니다.\r\n", members[member_index].borrowed_book);
} else {
printf("ℹ️ 대여 중인 도서가 없습니다.\r\n");
}
if (members[member_index].borrowed_time != 0) {
printf("ℹ️ 현재 대여 기간은 %d일입니다.\r\n", (int)(time(NULL) - members[member_index].borrowed_time) / ONE_DAY);
}
printf("--------------------------------\r\n");
printf("ℹ️ 대여는 1번, 반납은 2번을 눌러주세요.\r\n");
write_lcd(0, 0, "1. Borrow ");
write_lcd(0, 1, "2. Return ");
scanf("%d", &select_num);
if (select_num == 1) {
if (n_available_books == 0) {
printf("🚫 대여 가능한 도서가 없습니다.\r\n");
continue;
}
printf("📝 대여할 도서 번호를 입력해주세요.\r\n");
clear();
write_lcd(0, 0, "Enter the number");
write_lcd(0, 1, "of the book. ");
scanf("%d", &select_num);
if (select_num < 1 || select_num > 8) {
printf("🚫 잘못된 도서 번호입니다.\r\n");
continue;
}
if (available_books[select_num - 1] == 0) {
printf("🚫 이미 대출중인 도서입니다.\r\n");
continue;
}
if (select_num >= 1 && select_num <= 4) {
printf("❗️ 1️번 블록을 개방합니다.\r\n");
// write(sock, "1", 1);
clear();
write_lcd(0, 0, "Block 1 is open ");
delay(5000);
}
else if (select_num >= 5 && select_num <= 8) {
printf("❗️ 2️번 블록을 개방합니다.\r\n");
// write(sock, "2", 1);
clear();
write_lcd(0, 0, "Block 2 is open ");
delay(5000);
}
available_books[select_num - 1] = 0; // 대출중으로 변경
printf("✅ 대여가 완료되었습니다.\r\n");
clear();
write_lcd(0, 0, "Borrow complete ");
members[member_index].borrowed_book = select_num;
members[member_index].borrowed_time = time(NULL);
delay(3000);
} else if (select_num == 2) {
if (members[member_index].borrowed_book == 0) {
printf("🚫 대여 중인 도서가 없습니다.\r\n");
continue;
}
int return_book_num = members[member_index].borrowed_book;
printf("📝 반납할 도서 번호는 %d번 도서입니다.\r\n", return_book_num);
delay(1000);
if(return_book_num >= 1 && return_book_num <= 4) {
printf("❗️ 1️번 블록을 개방합니다.\r\n");
// write(sock, "1", 1);
clear();
write_lcd(0, 0, "Block 1 is open ");
delay(5000);
}
else if(return_book_num >= 5 && return_book_num <= 8) {
printf("❗️ 2️번 블록을 개방합니다.\r\n");
// write(sock, "2", 1);
clear();
write_lcd(0, 0, "Block 2 is open ");
delay(5000);
}
available_books[return_book_num - 1] = 1; // 반납으로 변경
members[member_index].borrowed_book = 0;
// 7일 연체 시 연체한 날짜만큼 제한
if ((int)(time(NULL) - members[member_index].borrowed_time) / ONE_DAY > 7) {
printf("🚫 연체로 인해 7일간 대출이 제한됩니다.\r\n");
delay(3000);
}
members[member_index].borrowed_time = 0;
printf("✅ 반납이 완료되었습니다.\r\n");
clear();
write_lcd(0, 0, "Return complete ");
delay(3000);
} else {
printf("🚫 잘못된 입력입니다.\r\n");
delay(3000);
continue;
}
}
}
}
\ No newline at end of file
File added
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment