54 Commits

Author SHA1 Message Date
Siegfried Kienzle
49a886d2ea remove thread.joinable 2017-06-15 19:21:03 +02:00
Siegfried Kienzle
d522a24c0f remove bug with thread 2017-06-15 19:18:02 +02:00
Siegfried Kienzle
c9bbfff992 implement destructor 2017-06-15 19:09:29 +02:00
Siegfried Kienzle
68433fc531 add an deconstructor 2017-06-15 19:00:27 +02:00
Siegfried Kienzle
25eb469203 add thread for rfid_reader 2017-06-15 18:22:49 +02:00
Siegfried Kienzle
509002b98f change pin of Reset 2017-06-15 17:48:33 +02:00
Siegfried Kienzle
2e5497e671 remove old rfid-implements 2017-06-15 17:06:59 +02:00
Siegfried Kienzle
f2544e40f0 try to implement code for rfid 2017-06-15 17:03:34 +02:00
Siegfried Kienzle
f7b66b811f try to implement rfid 2017-06-15 16:10:31 +02:00
Siegfried Kienzle
f9282ad540 try to implement rfid 2017-06-14 09:44:53 +02:00
Siegfried Kienzle
c92e91d760 implemented infrared_sensor-driver 2017-06-14 08:10:56 +02:00
Siegfried Kienzle
1b80f5b89e implemented infrared-modules 2017-06-14 08:08:33 +02:00
Siegfried Kienzle
f853d6b3e8 add some information about spi 2017-05-09 22:48:41 +02:00
Siegfried Kienzle
811e431b91 remove some bugs 2017-04-25 13:40:20 +02:00
kawaii
acb09659b6 add stop-function 2017-04-25 11:30:45 +00:00
kawaii
3cd610acf1 use argc and rename PIN_MOTOR-Flags 2017-04-25 10:22:28 +00:00
kawaii
a7f3a50c35 remove flag 2017-04-25 10:21:47 +00:00
Siegfried Kienzle
b2419a6593 remove some comment on gpio.c gpio.h and empty lines on motor.c 2017-04-25 10:56:22 +02:00
Siegfried Kienzle
1f483938e6 add function registerInput 2017-04-25 07:48:18 +02:00
Siegfried Kienzle
f5a9c9eac2 move defines to header-file 2017-04-25 07:36:03 +02:00
Siegfried Kienzle
73e359873f outsourcing of gpio-code 2017-04-25 07:33:40 +02:00
Siegfried Kienzle
1616dd670b outsourcing of gpio-code 2017-04-25 07:33:04 +02:00
Siegfried Kienzle
0bcdfb38a3 add include-instructions 2017-04-25 07:32:36 +02:00
kawaii
b1fc3e45b5 change GPIO_MOTOR1_PIN from GPIO6 to GPIO20 2017-02-01 01:11:44 +00:00
kawaii
60f989dbac add error-handling on file-deskriptor 2017-04-24 17:21:01 +00:00
Siegfried Kienzle
49a256b373 write an Makefile for motor.c 2017-04-22 17:35:50 +02:00
Siegfried Kienzle
644f053f9d begin to write motor.c 2017-04-22 17:35:29 +02:00
Siegfried Kienzle
70969386a6 create file motor.c 2017-04-22 15:57:35 +02:00
Michael Mächtel
6b08efc581 Merge pull request #1 from sikienzl/master
V1 + V2: Abgabe
2017-04-06 15:21:35 +02:00
Simon Wörner
f6327fc45d Merge pull request #10 from SWW13/travis-ci
Travis CI
2017-04-06 14:07:51 +02:00
Simon Wörner
54937c0b0b Merge pull request #9 from sikienzl/v2-delay-auswertung
V2: added Auswertung.md
2017-04-06 13:58:22 +02:00
Simon Wörner
d11fbff4ac added empty travis ci 2017-04-06 13:54:40 +02:00
Simon Wörner
e1aa450d6c added Auswertung.md 2017-04-06 13:10:05 +02:00
Simon Wörner
c61a74947f added render script and output png 2017-04-05 11:26:53 +02:00
kawaii
c796ca9d43 fixed led5 release build 2017-04-05 11:26:53 +02:00
Simon Wörner
beb8b2a987 Merge pull request #7 from SWW13/readme
modified README.md
2017-04-03 20:00:04 +02:00
Siegfried Kienzle
7aa17ef2eb modified README.md 2017-04-03 19:58:49 +02:00
Simon Wörner
2a086990df Merge pull request #6 from SWW13/v2-loop-rust
V2: loop (rust) + delay
2017-04-03 19:56:53 +02:00
Simon Wörner
e791c4fb6c fixed realtime arg help 2017-04-03 19:55:44 +02:00
Simon Wörner
20f4698db7 use CLOCK_MONOTONIC from libc, added os x support 2017-04-03 19:46:55 +02:00
Simon Wörner
bb066d5ba8 added documentation 2017-04-03 19:15:43 +02:00
Simon Wörner
c112baa562 rustfmt 2017-04-03 19:15:43 +02:00
Simon Wörner
64558495b1 added plot script and measured delays 2017-04-03 19:15:43 +02:00
Simon Wörner
b49df99659 added realtime parameter 2017-04-03 19:15:43 +02:00
Simon Wörner
c8914f364c moved sleep function to lib.rs 2017-04-03 19:15:42 +02:00
Simon Wörner
5f61004406 replace broken shuteye with libc 2017-04-03 19:15:33 +02:00
Simon Wörner
d4491f7dc1 fixed relativ delay with seconds 2017-04-03 19:10:51 +02:00
Simon Wörner
325ec5710f fixed cargo test 2017-04-03 19:10:50 +02:00
Simon Wörner
2fc9c4874f added argparser, multiple measurements and output 2017-04-03 19:10:34 +02:00
28b4e62767 Remove unnecessary nanosleep 2017-04-03 17:49:25 +02:00
22398b03aa V1 switch.c: Move duplicate code into function 2017-04-03 17:49:25 +02:00
ae5d5b638f V1: switch.c 2017-04-03 17:49:25 +02:00
Simon Wörner
37d89632a7 Revert "V1: switch.c" 2017-04-03 17:48:55 +02:00
Simon Wörner
d63bd4f35b measure sleep delay in loop 2017-04-02 11:04:51 +02:00
43 changed files with 4827 additions and 99 deletions

5
.travis.yml Normal file
View File

@@ -0,0 +1,5 @@
language: rust
rust:
- nightly
script:
- true

View File

@@ -81,9 +81,7 @@ fn main() {
chan_select! {
rpanic.recv() => { },
signal.recv() -> signal => {
#[cfg(debug_assertions)]
println!("received signal: {:?}", signal);
sdone.send(());
}
}

View File

@@ -1,120 +1,102 @@
/*
* switch.c
* How to register an button and count this
* author: Simon Wörner, Manuel Vögele,
* Siegfried Kienzle
* 24-March-2017
*
* */
#define BUTTON "17"
#define IN "in\n"
#define OUT "out\n"
#define HIGH "1\n"
#define LOW "0\n"
#define MAXBYTES 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
int writeIntoFile(char* value, char* path)
#define BASEPATH "/sys/class/gpio/"
#define GPIO_FOLDER "gpio%s/"
#define PIN_BUTTON "17"
#define PIN_LED "18"
#define LED_ON 0
#define LED_OFF 1
#define BUTTON_PRESSED 0
#define BUTTON_RELEASED 1
void writeFile(char *filename, char *buffer, size_t count)
{
int fd;
char buffer[3];
strcpy(buffer, value);
if((fd=open(path, O_RDWR | O_CREAT | O_TRUNC)) == -1) {
perror(NULL);
return EXIT_FAILURE;
}
if((write(fd, &buffer, sizeof(buffer))) == -1) {
perror("Cannot write into file");
return EXIT_FAILURE;
}
printf("Success");
close(fd);
return EXIT_SUCCESS;
int fd = open(filename, O_WRONLY);
write(fd, buffer, count);
close(fd);
}
int reserve(char* gpioPort)
void registerPin(char *pin)
{
char str[3];
strcpy(str, gpioPort);
strcat(str, "\n");
return writeIntoFile(str,"/sys/class/gpio/export");
writeFile(BASEPATH "export", pin, strlen(pin));
}
int setDirection(char* gpioPort, char* inOut)
void freePin(char *pin)
{
char *direc = "/direction";
char *gpioPath = "/sys/class/gpio/gpio";
char path[32];
strcpy(path, gpioPath);
strcat(path, gpioPort);
strcat(path, direc);
return writeIntoFile(inOut, path);
writeFile(BASEPATH "unexport", pin, strlen(pin));
}
int setOutput(char* gpioPort, char* volt)
void setDirection(char *pin, char *direction, int dirlen)
{
char *val = "/value";
char *gpioPath = "/sys/class/gpio/gpio";
char path[28];
strcpy(path, gpioPath);
strcat(path, gpioPort);
strcat(path, val);
return writeIntoFile(volt, path);
char path[50];
sprintf(path, BASEPATH GPIO_FOLDER "direction", pin);
writeFile(path, direction, dirlen);
}
int mainLoop(char* gpioPort)
void registerInput(char *pin)
{
int fid, portValue, count, countButton;
char *val = "/value";
char *gpioPath = "/sys/class/gpio/gpio";
char path[28];
strcpy(path, gpioPath);
strcat(path, gpioPort);
strcat(path, val);
while(true)
{
if( (fid=open(path, O_RDONLY)) == -1)
perror("Fehler ");
if(readInput(fid) == 1)
{
countButton++;
printf("%d", countButton);
}
close(fid);
}
registerPin(pin);
setDirection(pin, "in", 2);
}
char[] readInput(int fid)
void registerOutput(char *pin)
{
char buffer[MAXBYTES];
read(fid, &buffer, MAXBYTES);
return buffer;
registerPin(pin);
setDirection(pin, "out", 3);
}
int unexport(char* gpioport)
int readInput(char *pin)
{
char str[3];
strcpy(str, gpioPort);
strcat(str, "\n");
return writeIntoFile(str,"/sys/class/gpio/unexport");
char path[50];
int state;
sprintf(path, BASEPATH GPIO_FOLDER "value", pin);
FILE *fd = fopen(path, "r");
fscanf(fd, "%i", &state);
fclose(fd);
return state;
}
void writeOutput(char *pin, int state)
{
char path[50];
sprintf(path, BASEPATH GPIO_FOLDER "value", pin);
FILE *fd = fopen(path, "w");
fprintf(fd, "%i", state);
fclose(fd);
}
int main()
{
reserve(BUTTON);
setDirection(BUTTON, IN);
mainLoop(BUTTON);
unexport(BUTTON);
return 0;
{
struct timespec sleeptime, sleepremain;
int oldstate = BUTTON_PRESSED;
int state;
int count = 0;
registerInput(PIN_BUTTON);
registerOutput(PIN_LED);
sleeptime.tv_sec = 0;
sleeptime.tv_nsec = 1000000;
while (1)
{
nanosleep(&sleeptime, &sleepremain);
state = readInput(PIN_BUTTON);
if (state == BUTTON_PRESSED && oldstate == BUTTON_RELEASED)
{
count++;
printf("Number of button pushes: %i\n", count);
}
if (state == BUTTON_PRESSED)
writeOutput(PIN_LED, LED_ON);
else
writeOutput(PIN_LED, LED_OFF);
oldstate = state;
}
}

1
V2/delay/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
*.eps

41
V2/delay/Auswerung.md Normal file
View File

@@ -0,0 +1,41 @@
# Auswertung
## No Load
### No Realtime
Läuft der Prozess ohne Load und Realtime so liegt das Delay im Mean bei etwa **100µs**.
Der Ausreiser bei *11.000µs* Sleep Periode lässt sich durch eine kurze zeitigte Last durch einen Hintergrundprozess erklären, da bei jeder Messung (100 Durchläufe) immer der Worst Case betrachtet wird.
![delay_idle](delay_idle.png)
### Realtime
Im Vergleich dazu sinkt bei aktiver Realtime Priorität das Mean Delay auf etwa **25µs**.
Hier gibt es dafür mehr Ausreiser welche aber nicht über **190µs** hinaus gehen, auch hier lassen sich diese durch eine kurze zeitigte Last von einen Hintergrundprozess erklären.
![delay_idle_rt](delay_idle_rt.png)
## Load
### No Realtime
Bei Load ohne Realtime gibt es zu Begin einen großen Ausreiser mit über **10.000 µs**.
![delay_load](delay_load.png)
### Realtime
Durch die Realtime Priorität können solche Ausreiser vermieden werden, hier liegt der Mean etwas über dem ohne Last (etwa **27,5µs**) und die Ausreiser gehen bis knapp **55µs**.
Dies liegt immer weit unter den Werten ohne Load ohne Realtime Priorität.
![delay_load_rt](delay_load_rt.png)

BIN
V2/delay/delay_idle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

100
V2/delay/delay_idle.txt Normal file
View File

@@ -0,0 +1,100 @@
1000000 74885
2000000 70188
3000000 100960
4000000 96993
5000000 97920
6000000 95671
7000000 95193
8000000 96590
9000000 93091
10000000 99800
11000000 97447
12000000 604203
13000000 104094
14000000 95803
15000000 95638
16000000 102138
17000000 102025
18000000 91546
19000000 96641
20000000 99028
21000000 120893
22000000 100362
23000000 96186
24000000 97427
25000000 136011
26000000 97303
27000000 106304
28000000 101138
29000000 107326
30000000 98307
31000000 102672
32000000 126308
33000000 96300
34000000 98373
35000000 95499
36000000 96948
37000000 100012
38000000 145522
39000000 103847
40000000 99775
41000000 97942
42000000 100953
43000000 145006
44000000 100518
45000000 97123
46000000 97738
47000000 163093
48000000 96574
49000000 99272
50000000 102283
51000000 141284
52000000 110285
53000000 98504
54000000 99068
55000000 105413
56000000 116444
57000000 94664
58000000 106010
59000000 96990
60000000 116771
61000000 105616
62000000 101075
63000000 108201
64000000 100692
65000000 97401
66000000 96037
67000000 156027
68000000 101695
69000000 100123
70000000 96780
71000000 97292
72000000 98376
73000000 101387
74000000 95961
75000000 98504
76000000 100942
77000000 97391
78000000 100610
79000000 95913
80000000 96685
81000000 96468
82000000 162291
83000000 138063
84000000 97220
85000000 96690
86000000 103070
87000000 96431
88000000 102827
89000000 132035
90000000 97650
91000000 101599
92000000 96850
93000000 105641
94000000 100006
95000000 96558
96000000 96290
97000000 99299
98000000 97207
99000000 96728
100000000 99478

BIN
V2/delay/delay_idle_rt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

100
V2/delay/delay_idle_rt.txt Normal file
View File

@@ -0,0 +1,100 @@
1000000 16656
2000000 25916
3000000 21532
4000000 21365
5000000 28073
6000000 61812
7000000 25969
8000000 22677
9000000 28709
10000000 44480
11000000 47542
12000000 44199
13000000 26011
14000000 50844
15000000 24220
16000000 47490
17000000 30084
18000000 22418
19000000 24543
20000000 130157
21000000 87386
22000000 28783
23000000 41480
24000000 34803
25000000 51356
26000000 115667
27000000 57116
28000000 25699
29000000 27147
30000000 25419
31000000 25408
32000000 25971
33000000 25752
34000000 27513
35000000 22138
36000000 25356
37000000 24461
38000000 24919
39000000 26107
40000000 27034
41000000 27025
42000000 48784
43000000 188304
44000000 65535
45000000 72815
46000000 81399
47000000 89305
48000000 72733
49000000 27411
50000000 27557
51000000 101504
52000000 26026
53000000 25078
54000000 25693
55000000 22349
56000000 26401
57000000 27381
58000000 27996
59000000 23610
60000000 28079
61000000 22913
62000000 23371
63000000 28777
64000000 26476
65000000 27091
66000000 24528
67000000 23684
68000000 23675
69000000 22883
70000000 24904
71000000 26925
72000000 22332
73000000 24405
74000000 26530
75000000 23811
76000000 26094
77000000 22854
78000000 24511
79000000 22833
80000000 31417
81000000 21719
82000000 23324
83000000 26803
84000000 26585
85000000 26437
86000000 29864
87000000 26000
88000000 28438
89000000 28689
90000000 22794
91000000 23148
92000000 22096
93000000 26096
94000000 27233
95000000 25661
96000000 24244
97000000 25797
98000000 22609
99000000 25673
100000000 26861

BIN
V2/delay/delay_load.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

100
V2/delay/delay_load.txt Normal file
View File

@@ -0,0 +1,100 @@
1000000 10251030
2000000 81073
3000000 75124
4000000 74646
5000000 63594
6000000 74833
7000000 72323
8000000 75230
9000000 75063
10000000 73386
11000000 78688
12000000 76335
13000000 74814
14000000 76106
15000000 79221
16000000 72074
17000000 77377
18000000 113772
19000000 86679
20000000 81460
21000000 78170
22000000 85867
23000000 78670
24000000 78711
25000000 73493
26000000 73848
27000000 85347
28000000 77889
29000000 83868
30000000 71202
31000000 79993
32000000 72849
33000000 84765
34000000 95432
35000000 86151
36000000 82703
37000000 85662
38000000 82266
39000000 87048
40000000 76569
41000000 137860
42000000 74517
43000000 75653
44000000 77154
45000000 80841
46000000 74633
47000000 85665
48000000 297163
49000000 78457
50000000 86051
51000000 68436
52000000 75406
53000000 387268
54000000 84187
55000000 83396
56000000 76563
57000000 82334
58000000 83886
59000000 283875
60000000 73294
61000000 76200
62000000 78482
63000000 88784
64000000 77055
65000000 79389
66000000 115212
67000000 87911
68000000 79776
69000000 83620
70000000 91839
71000000 84277
72000000 74006
73000000 78058
74000000 81886
75000000 85627
76000000 79419
77000000 87691
78000000 85806
79000000 78192
80000000 74693
81000000 79631
82000000 94621
83000000 76486
84000000 72257
85000000 78811
86000000 88280
87000000 78009
88000000 104926
89000000 78459
90000000 83397
91000000 78648
92000000 67649
93000000 79722
94000000 78514
95000000 79025
96000000 67974
97000000 78225
98000000 78944
99000000 78830
100000000 67622

BIN
V2/delay/delay_load_rt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

100
V2/delay/delay_load_rt.txt Normal file
View File

@@ -0,0 +1,100 @@
1000000 22281
2000000 15345
3000000 14709
4000000 13867
5000000 14377
6000000 28221
7000000 37482
8000000 12732
9000000 21993
10000000 15681
11000000 27859
12000000 23578
13000000 23828
14000000 23871
15000000 22037
16000000 20413
17000000 23163
18000000 18153
19000000 23404
20000000 18447
21000000 24166
22000000 22385
23000000 28885
24000000 23510
25000000 21313
26000000 27656
27000000 18063
28000000 26386
29000000 18044
30000000 19023
31000000 19222
32000000 18534
33000000 23941
34000000 35909
35000000 18869
36000000 18025
37000000 36505
38000000 23891
39000000 19246
40000000 18246
41000000 24433
42000000 17966
43000000 27591
44000000 18935
45000000 20436
46000000 22770
47000000 19061
48000000 19833
49000000 24197
50000000 23719
51000000 19751
52000000 24636
53000000 19470
54000000 24147
55000000 27940
56000000 27722
57000000 18962
58000000 24368
59000000 19932
60000000 20911
61000000 19859
62000000 19745
63000000 24214
64000000 19048
65000000 25497
66000000 18716
67000000 27456
68000000 20415
69000000 23582
70000000 26332
71000000 20177
72000000 25270
73000000 19532
74000000 25042
75000000 24668
76000000 25543
77000000 33971
78000000 35887
79000000 46503
80000000 45504
81000000 52368
82000000 23348
83000000 36568
84000000 16037
85000000 16548
86000000 16017
87000000 37882
88000000 14955
89000000 22341
90000000 23477
91000000 14197
92000000 15749
93000000 22822
94000000 15521
95000000 45511
96000000 34095
97000000 49033
98000000 53501
99000000 36409
100000000 37909

11
V2/delay/render.sh Executable file
View File

@@ -0,0 +1,11 @@
#!/usr/bin/env bash
set -o xtrace
SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd)
cd "${SCRIPT_DIR}" && gnuplot -c sleep_delay.gp
while IFS= read -r -d '' f; do
output=$(echo "$f" | sed -E 's/\.eps$/.png/')
convert -density 300 "eps2:${f}" "$output"
done < <(find "${SCRIPT_DIR}" -name '*.eps' -print0)

20
V2/delay/sleep_delay.gp Normal file
View File

@@ -0,0 +1,20 @@
set title "{/=20 nanosleep delays}"
set terminal postscript eps enhanced
set xlabel "{/=20Period to sleep [nanoseconds]}"
set ylabel "{/=20Measured delay [nanoseconds]}"
set grid
set autoscale
set style data lines
show style data
set output 'delay_idle.eps'
plot 'delay_idle.txt' using ($1):($2) title "{/=17 Load: no, RT: no}" lw 6
set output 'delay_load.eps'
plot 'delay_load.txt' using ($1):($2) title "{/=17 Load: yes, RT: no}" lw 6
set output 'delay_idle_rt.eps'
plot 'delay_idle_rt.txt' using ($1):($2) title "{/=17 Load: no, RT: yes}" lw 6
set output 'delay_load_rt.eps'
plot 'delay_load_rt.txt' using ($1):($2) title "{/=17 Load: yes, RT: yes}" lw 6

62
V2/sleep/Cargo.lock generated Normal file
View File

@@ -0,0 +1,62 @@
[root]
name = "sleep"
version = "0.1.0"
dependencies = [
"argparse 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "argparse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libc"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "redox_syscall"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "time"
version = "0.1.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum argparse 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37bb99f5e39ee8b23b6e227f5b8f024207e8616f44aa4b8c76ecd828011667ef"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135"
"checksum redox_syscall 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "29dbdfd4b9df8ab31dec47c6087b7b13cbf4a776f335e4de8efba8288dda075b"
"checksum time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "211b63c112206356ef1ff9b19355f43740fc3f85960c598a93d3a3d3ba7beade"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"

9
V2/sleep/Cargo.toml Normal file
View File

@@ -0,0 +1,9 @@
[package]
name = "sleep"
version = "0.1.0"
authors = ["Simon Wörner <git@simon-woerner.de>"]
[dependencies]
argparse = ">=0.2.1"
libc = ">=0.2"
time = ">=0.1.36"

80
V2/sleep/src/lib.rs Normal file
View File

@@ -0,0 +1,80 @@
extern crate libc;
use std::time::Duration;
#[cfg(target_os = "linux")]
fn clock_nanosleep(clk_id: libc::clockid_t,
flags: libc::c_int,
rqtp: *const libc::timespec,
rmtp: *mut libc::timespec)
-> libc::c_int {
unsafe { libc::clock_nanosleep(clk_id, flags, rqtp as *const _, rmtp as *mut _) }
}
#[cfg(target_os = "macos")]
fn nanosleep(rqtp: *const libc::timespec, rmtp: *mut libc::timespec) -> libc::c_int {
unsafe { libc::nanosleep(rqtp as *const _, rmtp as *mut _) }
}
/// Sleeps for the given duration.
///
/// Uses `clock_nanosleep` on linux and `nanosleep` on darwin.
pub fn sleep(duration: Duration) -> Result<Duration, libc::c_int> {
let ts = duration_to_timespec(duration);
let mut remain = libc::timespec {
tv_sec: 0,
tv_nsec: 0,
};
#[cfg(target_os = "linux")]
let ret = clock_nanosleep(libc::CLOCK_MONOTONIC, 0, &ts, &mut remain);
#[cfg(target_os = "macos")]
let ret = nanosleep(&ts, &mut remain);
if ret == 0 {
Ok(timespec_to_duration(remain))
} else {
Err(ret)
}
}
fn duration_to_timespec(duration: Duration) -> libc::timespec {
libc::timespec {
tv_sec: duration.as_secs() as libc::time_t,
tv_nsec: duration.subsec_nanos() as libc::c_long,
}
}
fn timespec_to_duration(timespec: libc::timespec) -> Duration {
Duration::new(timespec.tv_sec as u64, timespec.tv_nsec as u32)
}
/// Set scheduler policy and priority for process with given pid.
///
/// If `pid` equals zero, the policy of the calling process will be set.
///
/// # Examples
///
/// ```rust
/// // set *round-robin* policy (default) and priority 99 (realtime) for own process
/// set_scheduler(0, libc::SCHED_RR, 99);
/// ```
#[cfg(target_os = "linux")]
pub fn set_scheduler(pid: libc::pid_t, policy: libc::c_int, priority: libc::c_int) -> libc::c_int {
let param = libc::sched_param { sched_priority: priority };
unsafe { libc::sched_setscheduler(pid, policy, &param) }
}
/// Set scheduler *round-robin* policy (default) and priority for own process.
///
/// # Examples
///
/// ```rust
/// // set *round-robin* policy (default) and priority 99 (realtime)
/// set_priority(99);
/// ```
#[cfg(target_os = "linux")]
pub fn set_priority(priority: i32) -> libc::c_int {
set_scheduler(0, libc::SCHED_RR, priority)
}

152
V2/sleep/src/main.rs Normal file
View File

@@ -0,0 +1,152 @@
#![feature(step_by)]
extern crate argparse;
extern crate sleep;
extern crate time;
use std::io::prelude::*;
use std::fs::File;
use std::path::Path;
use std::time::Duration;
use argparse::{ArgumentParser, Print, Store};
use sleep::sleep;
use time::precise_time_ns;
#[cfg(target_os = "linux")]
use argparse::StoreTrue;
#[cfg(target_os = "linux")]
use sleep::set_priority;
fn duration_from_ns(duration_ns: u64) -> Duration {
Duration::new(duration_ns / 1_000_000_000,
(duration_ns % 1_000_000_000) as u32)
}
fn duration_to_ns(duration: Duration) -> u64 {
duration.as_secs() * 1_000_000_000u64 + duration.subsec_nanos() as u64
}
fn measure_duration(sleep_duration: Duration) -> Duration {
let start = precise_time_ns();
let _remain = sleep(sleep_duration);
let end = precise_time_ns();
#[cfg(debug_assertions)]
println!("remain = {:?}", _remain);
let duration = end - start;
let duration = duration_from_ns(duration);
#[cfg(debug_assertions)]
println!("duration = {:?}", duration);
duration
}
fn measure_delay(sleep_duration: Duration) -> (Duration, Duration) {
let duration = measure_duration(sleep_duration);
let delay = duration - sleep_duration;
#[cfg(debug_assertions)]
println!("delay = {:?}", delay);
(duration, delay)
}
fn measure_delay_loop(sleep_duration: Duration, count: u64) -> Vec<(Duration, Duration)> {
println!("Starting measurment with period {}s {}ns for {} loops",
sleep_duration.as_secs(),
sleep_duration.subsec_nanos(),
count);
let mut data: Vec<(Duration, Duration)> = Vec::with_capacity(count as usize);
for _ in 0..count {
let (duration, delay) = measure_delay(sleep_duration);
data.push((duration, delay));
#[cfg(debug_assertions)]
print_delay(duration, delay);
}
data
}
fn print_delay(duration: Duration, delay: Duration) {
println!("value: {} s {} ns\tdelay: {} s {} ns\trelativ delay = {:.2}%\traw_data: {:?}",
duration.as_secs(),
duration.subsec_nanos(),
delay.as_secs(),
delay.subsec_nanos(),
(duration_to_ns(delay) * 100) as f64 / duration_to_ns(duration) as f64,
delay);
}
fn main() {
let mut min: u64 = 1_000_000;
let mut max: u64 = 100_000_000;
let mut step: u64 = 1_000_000;
let mut count: u64 = 100;
let mut output: String = "".to_string();
let mut file: Option<File> = None;
#[cfg(target_os = "linux")]
let mut realtime: bool = false;
#[cfg(target_os = "macos")]
let realtime: bool = false;
{
let mut ap = ArgumentParser::new();
ap.set_description(env!("CARGO_PKG_DESCRIPTION"));
ap.refer(&mut min).add_option(&["--min"], Store, "Sleep period start");
ap.refer(&mut max).add_option(&["--max"], Store, "Sleep period end");
ap.refer(&mut step).add_option(&["--step"], Store, "Sleep period step size");
ap.refer(&mut count).add_option(&["--loop"], Store, "Count of measurements per period");
#[cfg(target_os = "linux")]
ap.refer(&mut realtime).add_option(&["--rt"], StoreTrue, "Set realtime priority");
ap.refer(&mut output).add_option(&["-o", "--out"], Store, "Output file");
ap.add_option(&["-V", "--version"],
Print(env!("CARGO_PKG_VERSION").to_string()),
"Show version");
ap.parse_args_or_exit();
}
if realtime {
#[cfg(target_os = "linux")]
let ret = set_priority(99);
#[cfg(target_os = "macos")]
let ret = 0;
if ret != 0 {
panic!("Set realtime priority failed.");
}
}
if output != "" {
file = Some(File::create(Path::new(output.as_str())).expect(format!("Open file '{}' failed",
output)
.as_str()));
}
for duration in (min..max + 1).step_by(step) {
let data = measure_delay_loop(duration_from_ns(duration), count);
let max_delay = data.iter().max().expect("Max delay not found");
#[cfg(debug_assertions)]
println!("max_delay = {:?}", max_delay);
print_delay(max_delay.0, max_delay.1);
match file.as_ref() {
Some(mut f) => {
let value = format!("{: >9} {}\n", duration, duration_to_ns(max_delay.1));
f.write_all(value.as_bytes()).expect(format!("Write value '{}' to '{}' file failed",
value,
output)
.as_str());
}
None => {}
}
}
}

View File

@@ -3,10 +3,8 @@
ERROR=0
while IFS= read -r -d '' f; do
dir="$(dirname "${f}")"
echo "run 'cargo test' in ${dir}"
cd "${dir}" && cargo test
echo "run 'cargo test' with ${f}"
cargo test --manifest-path="${f}"
if [[ $? -ne 0 ]]; then
ERROR=1

29
project/Makefile Executable file
View File

@@ -0,0 +1,29 @@
# Makefile
CC=gcc
CFLAGS = -W -Wall -pedantic -g -std=gnu99 -c
LDFLAGS = -static
RM = rm -f
TARGET = motor
OBJECTS = gpio.o
HEADERS = $(OBJECTS:.o=.h)
SOURCES = $(TARGET).c $(OBJECTS:.o=.c)
%.o: %.c
$(CC) $(CFLAGS) $< -o $@
.PHONY: all clean
all: $(TARGET)
clean:
$(RM) $(TARGET) $(TARGET).o $(OBJECTS) depend
depend: $(SOURCES) $(HEADERS)
$(CC) $(CPPFLAGS) -MM $(SOURCES) > $@
$(TARGET): $(TARGET).o $(OBJECTS)
$(CC) $(LDFLAGS) $^ -o $@
$(RM) depend $(TARGET).o $(OBJECTS)
include depend

57
project/gpio.c Normal file
View File

@@ -0,0 +1,57 @@
#include<stdio.h>
#include<fcntl.h>
#include<string.h>
#include<unistd.h>
#include<string.h>
#include "gpio.h"
#define BASEPATH "/sys/class/gpio/"
#define GPIO_FOLDER "gpio%s/"
void writeFile(char *filename, char *buffer, size_t count)
{
int fd = open(filename, O_WRONLY);
if(fd == -1) {
perror("Fehler bei open ");
}
write(fd, buffer, count);
close(fd);
}
void registerPin(char *pin)
{
writeFile(BASEPATH "export", pin, strlen(pin));
}
void freePin(char *pin)
{
writeFile(BASEPATH "unexport", pin, strlen(pin));
}
void setDirection(char *pin, char *direction, int dirlen)
{
char path[50];
sprintf(path, BASEPATH GPIO_FOLDER "direction", pin);
writeFile(path, direction, dirlen);
}
void registerOutput(char *pin)
{
registerPin(pin);
setDirection(pin, "out", 3);
}
void registerInput(char *pin)
{
registerPin(pin);
setDirection(pin, "in", 3);
}
void writeOutput(char *pin, int state)
{
char path[50];
sprintf(path, BASEPATH GPIO_FOLDER "value", pin);
FILE *fd = fopen(path, "w");
fprintf(fd, "%i", state);
fclose(fd);
}

12
project/gpio.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef GPIO_H_
#define GPIO_H_
void writeFile(char *filename, char *buffer, size_t count);
void registerPin(char *pin);
void freePin(char *pin);
void setDirection(char *pin, char *direction, int dirlen);
void registerOutput(char *pin);
void registerInput(char *pin);
void writeOutput(char *pin, int state);
#endif

3
project/modules/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
.tmp_versions
*.ko.mod
*.o.cmd

43
project/modules/Makefile Normal file
View File

@@ -0,0 +1,43 @@
PWD = $(realpath $(shell pwd))
MODULE_NAME ?= $(shell basename "$(PWD)")
ifneq ($(KERNELRELEASE),)
# call from kernel build system
obj-m := $(MODULE_NAME).o
else
ARCH ?= aarch64
KERNEL_ARCH ?= arm64
CROSS_COMPILE ?= $(ARCH)-linux-gnu-
KVER ?= $(shell ls "$(PWD)/../../kernel" | grep 'linux-' | sed 's/linux-//')
KERNELDIR ?= $(PWD)/../../kernel/linux-$(KVER)
MODDESTDIR ?= /lib/modules/$(KVER)/kernel/drivers/syso
default:
ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(CROSS_COMPILE) MODULE_NAME=$(MODULE_NAME) $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
test: $(MODULE_NAME).ko.test
$(MODULE_NAME).ko.test: $(MODULE_NAME).test.o
$(CROSS_COMPILE)$(CC) $(LDFLAGS) -pthread $^ -o $@
%.o: %.c
$(CROSS_COMPILE)$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
clean:
rm -rf *.ko *.o *.mod.c *~ core .depend .*.cmd .tmp_versions *.symvers *.order
depend .depend dep:
$(CROSS_COMPILE)$(CC) $(CFLAGS) -M *.c > .depend
install:
install -p -m 644 $(MODULE_NAME).ko $(MODDESTDIR)
/sbin/depmod -a ${KVER}
uninstall:
rm -f $(MODDESTDIR)/$(MODULE_NAME).ko
/sbin/depmod -a ${KVER}
ifeq (.depend,$(wildcard .depend))
include .depend
endif

View File

@@ -0,0 +1,4 @@
static dev_t devno;
static struct cdev chardev;
static struct class *chardev_class;
static struct device *chardev_device[NUMBER_OF_MINOR_DEVICE];

View File

@@ -0,0 +1,82 @@
MODULE_AUTHOR("Manuel Vögele, Siegfried Kienzle, Simon Wörner");
MODULE_DESCRIPTION(DEVICE_NAME "driver");
MODULE_LICENSE("GPL");
static int __init ModInit(void)
{
unsigned int i = 0;
printk(KERN_DEBUG DEVICE_NAME ": init");
if (alloc_chrdev_region(&devno, 0, NUMBER_OF_MINOR_DEVICE, DEVICE_NAME) < 0)
return -EIO;
cdev_init(&chardev, &fops);
chardev.owner = THIS_MODULE;
chardev.ops = &fops;
if (cdev_add(&chardev, devno, NUMBER_OF_MINOR_DEVICE)) {
pr_err(DEVICE_NAME ": cdev_add failed.");
goto free_device_number;
}
chardev_class = class_create(THIS_MODULE, DEVICE_NAME);
if (IS_ERR(chardev_class)) {
pr_err(DEVICE_NAME ": no udev support\n");
goto free_cdev;
}
for (i = 0; i < NUMBER_OF_MINOR_DEVICE; ++i)
{
#if NUMBER_OF_MINOR_DEVICE == 1
chardev_device[i] = device_create(chardev_class, NULL, devno + i, NULL, DEVICE_NAME);
#else
chardev_device[i] = device_create(chardev_class, NULL, devno + i, NULL, DEVICE_NAME "%d", i);
#endif
if (IS_ERR(chardev_device[i])) {
pr_err(DEVICE_NAME ": device create failed\n");
goto free_device;
}
}
#ifdef CUSTOM_INIT
CUSTOM_INIT
#endif
return 0;
free_device:
for (; i > 0; --i) {
device_destroy(chardev_class, devno + i - 1);
}
class_destroy(chardev_class);
free_cdev:
cdev_del(&chardev);
free_device_number:
unregister_chrdev_region(devno, NUMBER_OF_MINOR_DEVICE);
return -EIO;
}
static void __exit ModExit(void)
{
unsigned int i = 0;
printk(KERN_DEBUG DEVICE_NAME ": exit");
#ifdef CUSTOM_EXIT
CUSTOM_EXIT
#endif
for (i = NUMBER_OF_MINOR_DEVICE; i > 0; --i) {
device_destroy(chardev_class, devno + i - 1);
}
class_destroy(chardev_class);
cdev_del(&chardev);
unregister_chrdev_region(devno, NUMBER_OF_MINOR_DEVICE);
}
module_init( ModInit );
module_exit( ModExit );

View File

@@ -0,0 +1 @@
cmd_/home/sikienzl/git/resy-ss17-grp1/project/modules/infrared_sensor_in_1/infrared_sensor_in_1.ko := aarch64-linux-gnu-ld -EL -r -T ./scripts/module-common.lds --build-id -o /home/sikienzl/git/resy-ss17-grp1/project/modules/infrared_sensor_in_1/infrared_sensor_in_1.ko /home/sikienzl/git/resy-ss17-grp1/project/modules/infrared_sensor_in_1/infrared_sensor_in_1.o /home/sikienzl/git/resy-ss17-grp1/project/modules/infrared_sensor_in_1/infrared_sensor_in_1.mod.o ; true

View File

@@ -0,0 +1 @@
../Makefile

View File

@@ -0,0 +1,77 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/gpio.h>
#include <linux/kobject.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#define DEVICE_NAME "infrared_sensor_in_1"
#define NUMBER_OF_MINOR_DEVICE (1)
#include "../_common/infrared_sensor.def.h"
static unsigned int infrared_sensor_in_1 = 2;
static unsigned int count = 0;
static int infrared_sensor_open(struct inode *devfile, struct file *instance)
{
int err;
err = gpio_request(infrared_sensor_in_1, "rpi-gpio-2");
if (err) {
printk("gpio_request for in_1 failed %d\n", err);
return -1;
}
err = gpio_direction_input(infrared_sensor_in_1);
if (err) {
printk("gpio_direction_input for in_1 failed %d\n", err);
gpio_free(infrared_sensor_in_1);
return -1;
}
printk("gpio 2 successfull configured\n");
return 0;
}
static ssize_t infrared_sensor_read( struct file *file, char __user *buffer, size_t length, loff_t *offset)
{
unsigned long not_copied;
u32 value=0;
printk(KERN_DEBUG DEVICE_NAME ": read");
if (*offset > 0) {
return 0;
}
value = gpio_get_value(infrared_sensor_in_1);
not_copied = copy_to_user(buffer, &value, count);
*offset += count - not_copied;
return count - not_copied;
}
static int infrared_sensor_close( struct inode *devfile, struct file *instance)
{
printk( "driver_close called\n" );
gpio_free( infrared_sensor_in_1 );
return 0;
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.open = infrared_sensor_open,
.release = infrared_sensor_close,
.read = infrared_sensor_read,
};
#include "../_common/infrared_sensor.h";

View File

@@ -0,0 +1 @@
../Makefile

View File

@@ -0,0 +1,77 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/gpio.h>
#include <linux/kobject.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#define DEVICE_NAME "infrared_sensor_in_2"
#define NUMBER_OF_MINOR_DEVICE (1)
#include "../_common/infrared_sensor.def.h"
static unsigned int infrared_sensor_in_2 = 3;
static unsigned int count = 0;
static int infrared_sensor_open(struct inode *devfile, struct file *instance)
{
int err;
err = gpio_request(infrared_sensor_in_2, "rpi-gpio-2");
if (err) {
printk("gpio_request for in_1 failed %d\n", err);
return -1;
}
err = gpio_direction_input(infrared_sensor_in_2);
if (err) {
printk("gpio_direction_input for in_1 failed %d\n", err);
gpio_free(infrared_sensor_in_2);
return -1;
}
printk("gpio 2 successfull configured\n");
return 0;
}
static ssize_t infrared_sensor_read( struct file *file, char __user *buffer, size_t length, loff_t *offset)
{
unsigned long not_copied;
u32 value=0;
printk(KERN_DEBUG DEVICE_NAME ": read");
if (*offset > 0) {
return 0;
}
value = gpio_get_value(infrared_sensor_in_2);
not_copied = copy_to_user(buffer, &value, count);
*offset += count - not_copied;
return count - not_copied;
}
static int infrared_sensor_close( struct inode *devfile, struct file *instance)
{
printk( "driver_close called\n" );
gpio_free( infrared_sensor_in_2 );
return 0;
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.open = infrared_sensor_open,
.release = infrared_sensor_close,
.read = infrared_sensor_read,
};
#include "../_common/infrared_sensor.h";

View File

@@ -0,0 +1 @@
../Makefile

View File

@@ -0,0 +1,77 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/gpio.h>
#include <linux/kobject.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#define DEVICE_NAME "infrared_sensor_in_3"
#define NUMBER_OF_MINOR_DEVICE (1)
#include "../_common/infrared_sensor.def.h"
static unsigned int infrared_sensor_in_3 = 4;
static unsigned int count = 0;
static int infrared_sensor_open(struct inode *devfile, struct file *instance)
{
int err;
err = gpio_request(infrared_sensor_in_3, "rpi-gpio-2");
if (err) {
printk("gpio_request for in_1 failed %d\n", err);
return -1;
}
err = gpio_direction_input(infrared_sensor_in_3);
if (err) {
printk("gpio_direction_input for in_1 failed %d\n", err);
gpio_free(infrared_sensor_in_3);
return -1;
}
printk("gpio 2 successfull configured\n");
return 0;
}
static ssize_t infrared_sensor_read( struct file *file, char __user *buffer, size_t length, loff_t *offset)
{
unsigned long not_copied;
u32 value=0;
printk(KERN_DEBUG DEVICE_NAME ": read");
if (*offset > 0) {
return 0;
}
value = gpio_get_value(infrared_sensor_in_3);
not_copied = copy_to_user(buffer, &value, count);
*offset += count - not_copied;
return count - not_copied;
}
static int infrared_sensor_close( struct inode *devfile, struct file *instance)
{
printk( "driver_close called\n" );
gpio_free( infrared_sensor_in_3 );
return 0;
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.open = infrared_sensor_open,
.release = infrared_sensor_close,
.read = infrared_sensor_read,
};
#include "../_common/infrared_sensor.h";

View File

@@ -0,0 +1 @@
../Makefile

View File

@@ -0,0 +1,76 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/gpio.h>
#include <linux/kobject.h>
#include <linux/device.h>
#include <linux/uaccess.h>
#define DEVICE_NAME "infrared_sensor_in_4"
#define NUMBER_OF_MINOR_DEVICE (1)
#include "../_common/infrared_sensor.def.h"
static unsigned int infrared_sensor_in_4 = 18;
static unsigned int count = 0;
static int infrared_sensor_open(struct inode *devfile, struct file *instance)
{
int err;
err = gpio_request(infrared_sensor_in_4, "rpi-gpio-2");
if (err) {
printk("gpio_request for in_1 failed %d\n", err);
return -1;
}
err = gpio_direction_input(infrared_sensor_in_4);
if (err) {
printk("gpio_direction_input for in_1 failed %d\n", err);
gpio_free(infrared_sensor_in_4);
return -1;
}
printk("gpio 2 successfull configured\n");
return 0;
}
static ssize_t infrared_sensor_read( struct file *file, char __user *buffer, size_t length, loff_t *offset)
{
unsigned long not_copied;
u32 value=0;
printk(KERN_DEBUG DEVICE_NAME ": read");
if (*offset > 0) {
return 0;
}
value = gpio_get_value(infrared_sensor_in_4);
not_copied = copy_to_user(buffer, &value, count);
*offset += count - not_copied;
return count - not_copied;
}
static int infrared_sensor_close( struct inode *devfile, struct file *instance)
{
printk( "driver_close called\n" );
gpio_free( infrared_sensor_in_4 );
return 0;
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.open = infrared_sensor_open,
.release = infrared_sensor_close,
.read = infrared_sensor_read,
};
#include "../_common/infrared_sensor.h";

134
project/motor.c Executable file
View File

@@ -0,0 +1,134 @@
#include<stdio.h>
#include<fcntl.h>
#include<string.h>
#include<unistd.h>
#include<string.h>
#include<stdbool.h>
#include "gpio.h"
#define PIN_MOTOR_RECHTS_FORWARD "20"
#define PIN_MOTOR_RECHTS_REVERSE "13"
#define PIN_MOTOR_LINKS_REVERSE "19"
#define PIN_MOTOR_LINKS_FORWARD "26"
#define MOTOR_ON 1
#define MOTOR_OFF 0
bool motor_rechts_on = false;
bool motor_links_on = false;
void forward(int motorNumber)
{
if(motorNumber == 1)
{
writeOutput(PIN_MOTOR_RECHTS_FORWARD, MOTOR_ON);
motor_rechts_on = true;
}
else if(motorNumber == 2)
{
writeOutput(PIN_MOTOR_LINKS_FORWARD, MOTOR_ON);
motor_links_on = true;
}
else if(motorNumber == 3)
{
writeOutput(PIN_MOTOR_RECHTS_FORWARD, MOTOR_ON);
writeOutput(PIN_MOTOR_LINKS_FORWARD, MOTOR_ON);
motor_rechts_on = true;
motor_links_on = true;
}
}
void reverse(int motorNumber)
{
if(motorNumber == 1)
{
writeOutput(PIN_MOTOR_RECHTS_REVERSE, MOTOR_ON);
motor_rechts_on = true;
}
else if(motorNumber == 2)
{
writeOutput(PIN_MOTOR_LINKS_REVERSE, MOTOR_ON);
motor_links_on = true;
}
else if(motorNumber == 3)
{
writeOutput(PIN_MOTOR_RECHTS_REVERSE, MOTOR_ON);
writeOutput(PIN_MOTOR_LINKS_REVERSE, MOTOR_ON);
motor_rechts_on = true;
motor_links_on = true;
}
}
void stopMotor(int motorNumber)
{
if(motorNumber == 1 && motor_rechts_on)
{
writeOutput(PIN_MOTOR_RECHTS_FORWARD, MOTOR_OFF);
writeOutput(PIN_MOTOR_RECHTS_REVERSE, MOTOR_OFF);
motor_rechts_on = false;
}
else if(motorNumber == 2 && motor_links_on)
{
writeOutput(PIN_MOTOR_LINKS_FORWARD, MOTOR_OFF);
writeOutput(PIN_MOTOR_LINKS_REVERSE, MOTOR_OFF);
motor_links_on = false;
}
}
int main(int argc, char* argv[])
{
registerOutput(PIN_MOTOR_RECHTS_FORWARD);
registerOutput(PIN_MOTOR_RECHTS_REVERSE);
registerOutput(PIN_MOTOR_LINKS_FORWARD);
registerOutput(PIN_MOTOR_LINKS_REVERSE);
if(argc > 0)
{
if(strcmp(argv[1],"1")==0)
{
//motor_rechts_forward
forward(1);
}
else if(strcmp(argv[1],"2")==0)
{
//motor_links_forward
forward(2);
}
else if(strcmp(argv[1],"3")==0)
{
//motor_rechts_reverse
reverse(1);
}
else if(strcmp(argv[1],"4")==0)
{
//motor_links_reverse
reverse(2);
}
else if(strcmp(argv[1],"5")==0)
{
forward(3);
}
else if(strcmp(argv[1],"6")==0)
{
//motor_rechts_forward stop
stopMotor(1);
}
else if(strcmp(argv[1],"7")==0)
{
//motor_links_forward stop
stopMotor(2);
}
else if(strcmp(argv[1],"0")==0)
{
freePin(PIN_MOTOR_RECHTS_FORWARD);
freePin(PIN_MOTOR_RECHTS_REVERSE);
freePin(PIN_MOTOR_LINKS_FORWARD);
freePin(PIN_MOTOR_LINKS_REVERSE);
}
}
return 0;
}

1755
project/rfid/MFRC522.cpp Normal file

File diff suppressed because it is too large Load Diff

323
project/rfid/MFRC522.h Normal file
View File

@@ -0,0 +1,323 @@
/**
* MFRC522.h - Library to use ARDUINO RFID MODULE KIT 13.56 MHZ WITH TAGS SPI W AND R BY COOQROBOT.
* Based on code Dr.Leong ( WWW.B2CQSHOP.COM )
* Created by Miguel Balboa (circuitito.com), Jan, 2012.
* Rewritten by Søren Thing Andersen (access.thing.dk), fall of 2013 (Translation to English, refactored, comments, anti collision, cascade levels.)
* Extended by Tom Clement with functionality to write to sector 0 of UID changeable Mifare cards.
* Released into the public domain.
*
-- Repurposed to fit Raspberry Pi ---
*/
#ifndef MFRC522_h
#define MFRC522_h
#include <stdint.h>
#include <stdio.h>
#include <string>
using namespace std;
typedef uint8_t byte;
typedef uint16_t word;
// Firmware data for self-test
// Reference values based on firmware version; taken from 16.1.1 in spec.
// Version 1.0
const byte MFRC522_firmware_referenceV1_0[] = {
0x00, 0xC6, 0x37, 0xD5, 0x32, 0xB7, 0x57, 0x5C,
0xC2, 0xD8, 0x7C, 0x4D, 0xD9, 0x70, 0xC7, 0x73,
0x10, 0xE6, 0xD2, 0xAA, 0x5E, 0xA1, 0x3E, 0x5A,
0x14, 0xAF, 0x30, 0x61, 0xC9, 0x70, 0xDB, 0x2E,
0x64, 0x22, 0x72, 0xB5, 0xBD, 0x65, 0xF4, 0xEC,
0x22, 0xBC, 0xD3, 0x72, 0x35, 0xCD, 0xAA, 0x41,
0x1F, 0xA7, 0xF3, 0x53, 0x14, 0xDE, 0x7E, 0x02,
0xD9, 0x0F, 0xB5, 0x5E, 0x25, 0x1D, 0x29, 0x79
};
// Version 2.0
const byte MFRC522_firmware_referenceV2_0[] = {
0x00, 0xEB, 0x66, 0xBA, 0x57, 0xBF, 0x23, 0x95,
0xD0, 0xE3, 0x0D, 0x3D, 0x27, 0x89, 0x5C, 0xDE,
0x9D, 0x3B, 0xA7, 0x00, 0x21, 0x5B, 0x89, 0x82,
0x51, 0x3A, 0xEB, 0x02, 0x0C, 0xA5, 0x00, 0x49,
0x7C, 0x84, 0x4D, 0xB3, 0xCC, 0xD2, 0x1B, 0x81,
0x5D, 0x48, 0x76, 0xD5, 0x71, 0x61, 0x21, 0xA9,
0x86, 0x96, 0x83, 0x38, 0xCF, 0x9D, 0x5B, 0x6D,
0xDC, 0x15, 0xBA, 0x3E, 0x7D, 0x95, 0x3B, 0x2F
};
class MFRC522 {
public:
// MFRC522 registers. Described in chapter 9 of the datasheet.
// When using SPI all addresses are shifted one bit left in the "SPI address byte" (section 8.1.2.3)
enum PCD_Register {
// Page 0: Command and status
// 0x00 // reserved for future use
CommandReg = 0x01 << 1, // starts and stops command execution
ComIEnReg = 0x02 << 1, // enable and disable interrupt request control bits
DivIEnReg = 0x03 << 1, // enable and disable interrupt request control bits
ComIrqReg = 0x04 << 1, // interrupt request bits
DivIrqReg = 0x05 << 1, // interrupt request bits
ErrorReg = 0x06 << 1, // error bits showing the error status of the last command executed
Status1Reg = 0x07 << 1, // communication status bits
Status2Reg = 0x08 << 1, // receiver and transmitter status bits
FIFODataReg = 0x09 << 1, // input and output of 64 byte FIFO buffer
FIFOLevelReg = 0x0A << 1, // number of bytes stored in the FIFO buffer
WaterLevelReg = 0x0B << 1, // level for FIFO underflow and overflow warning
ControlReg = 0x0C << 1, // miscellaneous control registers
BitFramingReg = 0x0D << 1, // adjustments for bit-oriented frames
CollReg = 0x0E << 1, // bit position of the first bit-collision detected on the RF interface
// 0x0F // reserved for future use
// Page 1: Command
// 0x10 // reserved for future use
ModeReg = 0x11 << 1, // defines general modes for transmitting and receiving
TxModeReg = 0x12 << 1, // defines transmission data rate and framing
RxModeReg = 0x13 << 1, // defines reception data rate and framing
TxControlReg = 0x14 << 1, // controls the logical behavior of the antenna driver pins TX1 and TX2
TxASKReg = 0x15 << 1, // controls the setting of the transmission modulation
TxSelReg = 0x16 << 1, // selects the internal sources for the antenna driver
RxSelReg = 0x17 << 1, // selects internal receiver settings
RxThresholdReg = 0x18 << 1, // selects thresholds for the bit decoder
DemodReg = 0x19 << 1, // defines demodulator settings
// 0x1A // reserved for future use
// 0x1B // reserved for future use
MfTxReg = 0x1C << 1, // controls some MIFARE communication transmit parameters
MfRxReg = 0x1D << 1, // controls some MIFARE communication receive parameters
// 0x1E // reserved for future use
SerialSpeedReg = 0x1F << 1, // selects the speed of the serial UART interface
// Page 2: Configuration
// 0x20 // reserved for future use
CRCResultRegH = 0x21 << 1, // shows the MSB and LSB values of the CRC calculation
CRCResultRegL = 0x22 << 1,
// 0x23 // reserved for future use
ModWidthReg = 0x24 << 1, // controls the ModWidth setting?
// 0x25 // reserved for future use
RFCfgReg = 0x26 << 1, // configures the receiver gain
GsNReg = 0x27 << 1, // selects the conductance of the antenna driver pins TX1 and TX2 for modulation
CWGsPReg = 0x28 << 1, // defines the conductance of the p-driver output during periods of no modulation
ModGsPReg = 0x29 << 1, // defines the conductance of the p-driver output during periods of modulation
TModeReg = 0x2A << 1, // defines settings for the internal timer
TPrescalerReg = 0x2B << 1, // the lower 8 bits of the TPrescaler value. The 4 high bits are in TModeReg.
TReloadRegH = 0x2C << 1, // defines the 16-bit timer reload value
TReloadRegL = 0x2D << 1,
TCounterValueRegH = 0x2E << 1, // shows the 16-bit timer value
TCounterValueRegL = 0x2F << 1,
// Page 3: Test Registers
// 0x30 // reserved for future use
TestSel1Reg = 0x31 << 1, // general test signal configuration
TestSel2Reg = 0x32 << 1, // general test signal configuration
TestPinEnReg = 0x33 << 1, // enables pin output driver on pins D1 to D7
TestPinValueReg = 0x34 << 1, // defines the values for D1 to D7 when it is used as an I/O bus
TestBusReg = 0x35 << 1, // shows the status of the internal test bus
AutoTestReg = 0x36 << 1, // controls the digital self test
VersionReg = 0x37 << 1, // shows the software version
AnalogTestReg = 0x38 << 1, // controls the pins AUX1 and AUX2
TestDAC1Reg = 0x39 << 1, // defines the test value for TestDAC1
TestDAC2Reg = 0x3A << 1, // defines the test value for TestDAC2
TestADCReg = 0x3B << 1 // shows the value of ADC I and Q channels
// 0x3C // reserved for production tests
// 0x3D // reserved for production tests
// 0x3E // reserved for production tests
// 0x3F // reserved for production tests
};
// MFRC522 commands. Described in chapter 10 of the datasheet.
enum PCD_Command {
PCD_Idle = 0x00, // no action, cancels current command execution
PCD_Mem = 0x01, // stores 25 bytes into the internal buffer
PCD_GenerateRandomID = 0x02, // generates a 10-byte random ID number
PCD_CalcCRC = 0x03, // activates the CRC coprocessor or performs a self test
PCD_Transmit = 0x04, // transmits data from the FIFO buffer
PCD_NoCmdChange = 0x07, // no command change, can be used to modify the CommandReg register bits without affecting the command, for example, the PowerDown bit
PCD_Receive = 0x08, // activates the receiver circuits
PCD_Transceive = 0x0C, // transmits data from FIFO buffer to antenna and automatically activates the receiver after transmission
PCD_MFAuthent = 0x0E, // performs the MIFARE standard authentication as a reader
PCD_SoftReset = 0x0F // resets the MFRC522
};
// MFRC522 RxGain[2:0] masks, defines the receiver's signal voltage gain factor (on the PCD).
// Described in 9.3.3.6 / table 98 of the datasheet at http://www.nxp.com/documents/data_sheet/MFRC522.pdf
enum PCD_RxGain {
RxGain_18dB = 0x00 << 4, // 000b - 18 dB, minimum
RxGain_23dB = 0x01 << 4, // 001b - 23 dB
RxGain_18dB_2 = 0x02 << 4, // 010b - 18 dB, it seems 010b is a duplicate for 000b
RxGain_23dB_2 = 0x03 << 4, // 011b - 23 dB, it seems 011b is a duplicate for 001b
RxGain_33dB = 0x04 << 4, // 100b - 33 dB, average, and typical default
RxGain_38dB = 0x05 << 4, // 101b - 38 dB
RxGain_43dB = 0x06 << 4, // 110b - 43 dB
RxGain_48dB = 0x07 << 4, // 111b - 48 dB, maximum
RxGain_min = 0x00 << 4, // 000b - 18 dB, minimum, convenience for RxGain_18dB
RxGain_avg = 0x04 << 4, // 100b - 33 dB, average, convenience for RxGain_33dB
RxGain_max = 0x07 << 4 // 111b - 48 dB, maximum, convenience for RxGain_48dB
};
// Commands sent to the PICC.
enum PICC_Command {
// The commands used by the PCD to manage communication with several PICCs (ISO 14443-3, Type A, section 6.4)
PICC_CMD_REQA = 0x26, // REQuest command, Type A. Invites PICCs in state IDLE to go to READY and prepare for anticollision or selection. 7 bit frame.
PICC_CMD_WUPA = 0x52, // Wake-UP command, Type A. Invites PICCs in state IDLE and HALT to go to READY(*) and prepare for anticollision or selection. 7 bit frame.
PICC_CMD_CT = 0x88, // Cascade Tag. Not really a command, but used during anti collision.
PICC_CMD_SEL_CL1 = 0x93, // Anti collision/Select, Cascade Level 1
PICC_CMD_SEL_CL2 = 0x95, // Anti collision/Select, Cascade Level 2
PICC_CMD_SEL_CL3 = 0x97, // Anti collision/Select, Cascade Level 3
PICC_CMD_HLTA = 0x50, // HaLT command, Type A. Instructs an ACTIVE PICC to go to state HALT.
// The commands used for MIFARE Classic (from http://www.nxp.com/documents/data_sheet/MF1S503x.pdf, Section 9)
// Use PCD_MFAuthent to authenticate access to a sector, then use these commands to read/write/modify the blocks on the sector.
// The read/write commands can also be used for MIFARE Ultralight.
PICC_CMD_MF_AUTH_KEY_A = 0x60, // Perform authentication with Key A
PICC_CMD_MF_AUTH_KEY_B = 0x61, // Perform authentication with Key B
PICC_CMD_MF_READ = 0x30, // Reads one 16 byte block from the authenticated sector of the PICC. Also used for MIFARE Ultralight.
PICC_CMD_MF_WRITE = 0xA0, // Writes one 16 byte block to the authenticated sector of the PICC. Called "COMPATIBILITY WRITE" for MIFARE Ultralight.
PICC_CMD_MF_DECREMENT = 0xC0, // Decrements the contents of a block and stores the result in the internal data register.
PICC_CMD_MF_INCREMENT = 0xC1, // Increments the contents of a block and stores the result in the internal data register.
PICC_CMD_MF_RESTORE = 0xC2, // Reads the contents of a block into the internal data register.
PICC_CMD_MF_TRANSFER = 0xB0, // Writes the contents of the internal data register to a block.
// The commands used for MIFARE Ultralight (from http://www.nxp.com/documents/data_sheet/MF0ICU1.pdf, Section 8.6)
// The PICC_CMD_MF_READ and PICC_CMD_MF_WRITE can also be used for MIFARE Ultralight.
PICC_CMD_UL_WRITE = 0xA2 // Writes one 4 byte page to the PICC.
};
// MIFARE constants that does not fit anywhere else
enum MIFARE_Misc {
MF_ACK = 0xA, // The MIFARE Classic uses a 4 bit ACK/NAK. Any other value than 0xA is NAK.
MF_KEY_SIZE = 6 // A Mifare Crypto1 key is 6 bytes.
};
// PICC types we can detect. Remember to update PICC_GetTypeName() if you add more.
enum PICC_Type {
PICC_TYPE_UNKNOWN = 0,
PICC_TYPE_ISO_14443_4 = 1, // PICC compliant with ISO/IEC 14443-4
PICC_TYPE_ISO_18092 = 2, // PICC compliant with ISO/IEC 18092 (NFC)
PICC_TYPE_MIFARE_MINI = 3, // MIFARE Classic protocol, 320 bytes
PICC_TYPE_MIFARE_1K = 4, // MIFARE Classic protocol, 1KB
PICC_TYPE_MIFARE_4K = 5, // MIFARE Classic protocol, 4KB
PICC_TYPE_MIFARE_UL = 6, // MIFARE Ultralight or Ultralight C
PICC_TYPE_MIFARE_PLUS = 7, // MIFARE Plus
PICC_TYPE_TNP3XXX = 8, // Only mentioned in NXP AN 10833 MIFARE Type Identification Procedure
PICC_TYPE_NOT_COMPLETE = 255 // SAK indicates UID is not complete.
};
// Return codes from the functions in this class. Remember to update GetStatusCodeName() if you add more.
enum StatusCode {
STATUS_OK = 1, // Success
STATUS_ERROR = 2, // Error in communication
STATUS_COLLISION = 3, // Collission detected
STATUS_TIMEOUT = 4, // Timeout in communication.
STATUS_NO_ROOM = 5, // A buffer is not big enough.
STATUS_INTERNAL_ERROR = 6, // Internal error in the code. Should not happen ;-)
STATUS_INVALID = 7, // Invalid argument.
STATUS_CRC_WRONG = 8, // The CRC_A does not match
STATUS_MIFARE_NACK = 9 // A MIFARE PICC responded with NAK.
};
// A struct used for passing the UID of a PICC.
typedef struct {
byte size; // Number of bytes in the UID. 4, 7 or 10.
byte uidByte[10];
byte sak; // The SAK (Select acknowledge) byte returned from the PICC after successful selection.
} Uid;
// A struct used for passing a MIFARE Crypto1 key
typedef struct {
byte keyByte[MF_KEY_SIZE];
} MIFARE_Key;
// Member variables
Uid uid; // Used by PICC_ReadCardSerial().
// Size of the MFRC522 FIFO
static const byte FIFO_SIZE = 64; // The FIFO is 64 bytes.
/////////////////////////////////////////////////////////////////////////////////////
// Functions for setting up the Raspberry Pi
/////////////////////////////////////////////////////////////////////////////////////
MFRC522();
void setSPIConfig();
/////////////////////////////////////////////////////////////////////////////////////
// Basic interface functions for communicating with the MFRC522
/////////////////////////////////////////////////////////////////////////////////////
void PCD_WriteRegister(byte reg, byte value);
void PCD_WriteRegister(byte reg, byte count, byte *values);
byte PCD_ReadRegister(byte reg);
void PCD_ReadRegister(byte reg, byte count, byte *values, byte rxAlign = 0);
void setBitMask(unsigned char reg, unsigned char mask);
void PCD_SetRegisterBitMask(byte reg, byte mask);
void PCD_ClearRegisterBitMask(byte reg, byte mask);
byte PCD_CalculateCRC(byte *data, byte length, byte *result);
/////////////////////////////////////////////////////////////////////////////////////
// Functions for manipulating the MFRC522
/////////////////////////////////////////////////////////////////////////////////////
void PCD_Init();
void PCD_Reset();
void PCD_AntennaOn();
void PCD_AntennaOff();
byte PCD_GetAntennaGain();
void PCD_SetAntennaGain(byte mask);
bool PCD_PerformSelfTest();
/////////////////////////////////////////////////////////////////////////////////////
// Functions for communicating with PICCs
/////////////////////////////////////////////////////////////////////////////////////
byte PCD_TransceiveData(byte *sendData, byte sendLen, byte *backData, byte *backLen, byte *validBits = NULL, byte rxAlign = 0, bool checkCRC = false);
byte PCD_CommunicateWithPICC(byte command, byte waitIRq, byte *sendData, byte sendLen, byte *backData = NULL, byte *backLen = NULL, byte *validBits = NULL, byte rxAlign = 0, bool checkCRC = false);
byte PICC_RequestA(byte *bufferATQA, byte *bufferSize);
byte PICC_WakeupA(byte *bufferATQA, byte *bufferSize);
byte PICC_REQA_or_WUPA(byte command, byte *bufferATQA, byte *bufferSize);
byte PICC_Select(Uid *uid, byte validBits = 0);
byte PICC_HaltA();
/////////////////////////////////////////////////////////////////////////////////////
// Functions for communicating with MIFARE PICCs
/////////////////////////////////////////////////////////////////////////////////////
byte PCD_Authenticate(byte command, byte blockAddr, MIFARE_Key *key, Uid *uid);
void PCD_StopCrypto1();
byte MIFARE_Read(byte blockAddr, byte *buffer, byte *bufferSize);
byte MIFARE_Write(byte blockAddr, byte *buffer, byte bufferSize);
byte MIFARE_Decrement(byte blockAddr, long delta);
byte MIFARE_Increment(byte blockAddr, long delta);
byte MIFARE_Restore(byte blockAddr);
byte MIFARE_Transfer(byte blockAddr);
byte MIFARE_Ultralight_Write(byte page, byte *buffer, byte bufferSize);
byte MIFARE_GetValue(byte blockAddr, long *value);
byte MIFARE_SetValue(byte blockAddr, long value);
/////////////////////////////////////////////////////////////////////////////////////
// Support functions
/////////////////////////////////////////////////////////////////////////////////////
byte PCD_MIFARE_Transceive(byte *sendData, byte sendLen, bool acceptTimeout = false);
// old function used too much memory, now name moved to flash; if you need char, copy from flash to memory
//const char *GetStatusCodeName(byte code);
const string GetStatusCodeName(byte code);
byte PICC_GetType(byte sak);
// old function used too much memory, now name moved to flash; if you need char, copy from flash to memory
//const char *PICC_GetTypeName(byte type);
const string PICC_GetTypeName(byte type);
void PICC_DumpToSerial(Uid *uid);
void PICC_DumpMifareClassicToSerial(Uid *uid, byte piccType, MIFARE_Key *key);
void PICC_DumpMifareClassicSectorToSerial(Uid *uid, MIFARE_Key *key, byte sector);
void PICC_DumpMifareUltralightToSerial();
void MIFARE_SetAccessBits(byte *accessBitBuffer, byte g0, byte g1, byte g2, byte g3);
bool MIFARE_OpenUidBackdoor(bool logErrors);
bool MIFARE_SetUid(byte *newUid, byte uidSize, bool logErrors);
bool MIFARE_UnbrickUidSector(bool logErrors);
/////////////////////////////////////////////////////////////////////////////////////
// Convenience functions - does not add extra functionality
/////////////////////////////////////////////////////////////////////////////////////
bool PICC_IsNewCardPresent();
bool PICC_ReadCardSerial();
private:
byte MIFARE_TwoStepHelper(byte command, byte blockAddr, long data);
};
#endif

1129
project/rfid/bcm2835.h Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,54 @@
#include "rfid_reader.hpp"
#include <unistd.h>
#include <iostream>
#include <chrono>
#include <ctime>
rfid_reader::rfid_reader()
{
mfrc.PCD_Init();
thread = std::thread(&rfid_reader::loop, this);
}
rfid_reader::~rfid_reader()
{
stop_thread = true;
thread.join();
}
uint32_t rfid_reader::last_id() const
{
return uid;
}
void rfid_reader::loop()
{
stop_thread = false;
while(!stop_thread)
{
if(!mfrc.PICC_IsNewCardPresent())
{
continue;
}
if(!mfrc.PICC_ReadCardSerial())
{
continue;
}
uid = int((unsigned char)(mfrc.uid.uidByte[0]) << 24 |
(unsigned char)(mfrc.uid.uidByte[1]) << 16 |
(unsigned char)(mfrc.uid.uidByte[2]) << 8 |
(unsigned char)(mfrc.uid.uidByte[3]));
#ifndef NDEBUG
printf("\n");
std::time_t result = std::time(nullptr);
std::cout << std::asctime(std::localtime(&result));
printf("%X\n", last_id());
#endif
std::this_thread::sleep_for(1s);
}
}

View File

@@ -0,0 +1,27 @@
#ifndef RFIDREADER_HPP_
#define RFIDREADER_HPP_
#include <cstdint>
#include <thread>
#include "MFRC522.h"
class rfid_reader
{
public:
uint32_t last_id() const;
rfid_reader();
rfid_reader(const rfid_reader &) = delete;
rfid_reader(const rfid_reader &&) = delete;
~rfid_reader();
void loop();
private:
MFRC522 mfrc;
uint32_t uid;
std::thread thread;
bool stop_thread;
};
#endif

View File

@@ -0,0 +1,5 @@
How to enable the SPI Interface:
edit /boot/config.txt
add line dtparam=spi=on