Xavier L'Heureux commited on
Commit
2db1521
0 Parent(s):

Initial commit

Browse files
Files changed (13) hide show
  1. .envrc +1 -0
  2. .gitattributes +2 -0
  3. boot.txt +63 -0
  4. commands.md +5 -0
  5. demo.py +115 -0
  6. linux-image-4.14.98-imx_12-4_arm64.deb +3 -0
  7. model.tflite +0 -0
  8. model_quantized.tflite +0 -0
  9. net.py +40 -0
  10. overlays.txt +2 -0
  11. portiloop.dts +141 -0
  12. sample.mp3 +0 -0
  13. shell.nix +17 -0
.envrc ADDED
@@ -0,0 +1 @@
 
1
+ use nix
.gitattributes ADDED
@@ -0,0 +1,2 @@
 
 
1
+ *.deb filter=lfs diff=lfs merge=lfs -text
2
+ *.wav filter=lfs diff=lfs merge=lfs -text
boot.txt ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ fdt_addr=0x43000000
2
+ image=Image
3
+ script=boot.scr
4
+ mmc_root="PARTUUID=70672ec3-5eee-49ff-b3b1-eb1fbd406bf5"
5
+ sd_root="/dev/mmcblk1p2"
6
+
7
+ # Check boot device to decide which root partition to use
8
+ if test ${bootdev} = 1; then
9
+ setenv root ${sd_root}
10
+ else
11
+ setenv root ${mmc_root}
12
+ fi
13
+
14
+ if test ${baseboardid} = 1; then
15
+ setenv fdt_file fsl-imx8mq-phanbell.dtb
16
+ elif test ${baseboardid} = 2; then
17
+ setenv fdt_file fsl-imx8mq-yorktown.dtb
18
+ else
19
+ # EVT Boards have quirky baseboard ID resistors, so fall back
20
+ # to phanbell if we're unsure what the board is.
21
+ echo "Unknown baseboard revision, selecting phanbell dtb."
22
+ setenv fdt_file fsl-imx8mq-phanbell.dtb
23
+ fi
24
+
25
+ cmdline="console=ttymxc0,115200 console=tty0 earlycon=ec_imx6q,0x30860000,115200 root=${root} rootfstype=ext4 rw rootwait init=/sbin/init net.ifnames=0 pci=pcie_bus_perf"
26
+
27
+ ext2load mmc ${bootdev}:1 ${loadaddr} ${image}
28
+ setenv bootargs ${cmdline} ${extra_bootargs}
29
+
30
+ #Load base device tree.
31
+ ext2load mmc ${bootdev}:1 ${fdt_addr} ${fdt_file}
32
+ fdt addr ${fdt_addr}
33
+ fdt resize 4096 # PORTILOOP: Add extra 4096 bytes to fit overlay
34
+
35
+ # Load overlays to arbitrary address beyond fdt location (will apply them later).
36
+ setexpr fdtovaddr ${fdt_addr} + F000
37
+
38
+ # Parse overlays.txt and apply individual overlays.
39
+ if ext2load mmc ${bootdev}:1 ${fdtovaddr} overlays.txt && env import -t ${fdtovaddr} ${filesize} && test -n ${overlay}; then
40
+ echo loaded overlay.txt: ${overlay}
41
+ for ov in ${overlay}; do
42
+ if ext2load mmc ${bootdev}:1 ${fdtovaddr} ${ov}.dtbo && fdt apply ${fdtovaddr}; then
43
+ echo overlay of ${ov} successful
44
+ else
45
+ echo overlay failed, reverting to original device tree
46
+ ext2load mmc ${bootdev}:1 ${fdt_addr} ${fdt_file}
47
+ booti ${loadaddr} - ${fdt_addr}
48
+ fi
49
+ done
50
+ fi
51
+
52
+ if printenv m4enabled; then
53
+ if test ${m4enabled} = 1; then
54
+ if ext2load mmc ${bootdev}:1 ${fdtovaddr} fsl-imx8mq-phanbell-m4.dtbo && fdt apply ${fdtovaddr}; then
55
+ echo M4 overlay loaded, starting core
56
+ run m4boot
57
+ else
58
+ echo M4 overlay failed
59
+ fi
60
+ fi
61
+ fi
62
+
63
+ booti ${loadaddr} - ${fdt_addr}
commands.md ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
1
+ # Build scr
2
+ sudo mkimage -A arm -T script -O linux -d boot.txt /boot/boot.scr
3
+
4
+ # Edit device tree overlay
5
+ sudo vim /boot/portiloop.dts && sudo dtc -I dts -O dtb -o /boot/portiloop.dtbo /boot/portiloop.dts
demo.py ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from periphery import GPIO, PWM, SPI, I2C
2
+ from spidev import SpiDev
3
+ from time import sleep
4
+
5
+ led1_R = PWM(0, 0)
6
+ led1_B = PWM(2, 0)
7
+ led1_gnd = PWM(1, 0)
8
+
9
+ led2_R = GPIO("/dev/gpiochip0", 8, "out")
10
+ led2_B = GPIO("/dev/gpiochip0", 6, "out")
11
+ led2_gnd = GPIO("/dev/gpiochip0", 7, "out")
12
+
13
+ led3_R = GPIO("/dev/gpiochip2", 0, "out")
14
+ #led3_B = GPIO("/dev/gpiochip2", 5, "out")
15
+ led3_gnd = GPIO("/dev/gpiochip2", 8, "out")
16
+
17
+ aquisition = GPIO("/dev/gpiochip2", 20, "out")
18
+
19
+ frontend_nrst = GPIO("/dev/gpiochip2", 9, "out")
20
+ frontend_npwdn = GPIO("/dev/gpiochip2", 12, "out")
21
+ frontend_start = GPIO("/dev/gpiochip3", 29, "out")
22
+ frontend_ = SpiDev()
23
+ frontend_.open(0, 0)
24
+ frontend_.max_speed_hz = 8000000
25
+ frontend_.mode = 0b01
26
+
27
+ audio = I2C("/dev/i2c-1")
28
+ AUDIO_ADDR = 0x68
29
+
30
+ aquisition.write(True)
31
+ sleep(0.5)
32
+ aquisition.write(False)
33
+ sleep(0.5)
34
+ aquisition.write(True)
35
+
36
+ try:
37
+ frontend_npwdn.write(True)
38
+ frontend_start.write(False)
39
+ sleep(0.1)
40
+ frontend_nrst.write(False)
41
+ sleep(0.01)
42
+ frontend_nrst.write(True)
43
+ sleep(0.1)
44
+ frontend_.xfer([0x11])
45
+
46
+ data_out = [0x20, 0x00, 0x00]
47
+ data_in = frontend_.xfer(list(data_out))
48
+
49
+ assert data_in[2] == 0x3E, "Wrong output"
50
+ print("EEG Frontend responsive")
51
+ finally:
52
+ frontend_.close()
53
+
54
+ try:
55
+ for reg in [0x0000, 0x0002, 0x0004, 0x0006, 0x000A, 0x000E, 0x0010, 0x0014, 0x0020, 0x0022, 0x0024, 0x0026, 0x0028, 0x002A, 0x002C, 0x002E, 0x0030, 0x0032, 0x0034, 0x0036, 0x0038, 0x003A, 0x003C, 0x0100, 0x0102, 0x0104, 0x0106, 0x0108, 0x010A, 0x010C, 0x010E, 0x0110, 0x0116]:
56
+ msgs = [I2C.Message([reg >> 8, reg & 0xFF]), I2C.Message([0x00, 0x00], read=True)]
57
+ audio.transfer(AUDIO_ADDR, msgs)
58
+ print("0x{:04x}: 0x{:02x} 0x{:02x}".format(reg, msgs[1].data[0], msgs[1].data[1]))
59
+ finally:
60
+ audio.close()
61
+
62
+ state = 0
63
+ try:
64
+ led1_R.frequency = 1e3
65
+ led1_R.enable()
66
+ led1_B.frequency = 1e3
67
+ led1_B.enable()
68
+ led1_gnd.frequency = 1e3
69
+ led1_gnd.enable()
70
+ led1_gnd.duty_cycle = 0.0
71
+ for i in range(200):
72
+ led1_R.duty_cycle = (state % 10) / 10
73
+ led1_B.duty_cycle = (state // 10) / 10
74
+ state = (state + 1) % 100
75
+ sleep(0.02)
76
+ finally:
77
+ led1_R.duty_cycle = 0.0
78
+ led1_R.close()
79
+ led1_B.duty_cycle = 0.0
80
+ led1_B.close()
81
+ led1_gnd.duty_cycle = 0.0
82
+ led1_gnd.close()
83
+
84
+ state = 0
85
+ try:
86
+ led2_gnd.write(False)
87
+ for i in range(12):
88
+ led2_R.write(state % 2 == 1)
89
+ led2_B.write(state // 2 == 1)
90
+ state = (state + 1) % 4
91
+ sleep(0.2)
92
+ finally:
93
+ led2_R.write(False)
94
+ led2_R.close()
95
+ led2_B.write(False)
96
+ led2_B.close()
97
+ led2_gnd.write(False)
98
+ led2_gnd.close()
99
+
100
+ state = 0
101
+ try:
102
+ led3_gnd.write(False)
103
+ for i in range(12):
104
+ state = 3
105
+ led3_R.write(state % 2 == 1)
106
+ #led3_B.write(state // 2 == 1)
107
+ state = (state + 1) % 4
108
+ sleep(0.2)
109
+ finally:
110
+ led3_R.write(False)
111
+ led3_R.close()
112
+ #led3_B.write(False)
113
+ #led3_B.close()
114
+ led3_gnd.write(False)
115
+ led3_gnd.close()
linux-image-4.14.98-imx_12-4_arm64.deb ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:74d6a69d76d03fb59bffd60d6c1d3229bb9307f5e64a1f2c8af6ce2233dffa0d
3
+ size 11093740
model.tflite ADDED
Binary file (73.1 kB). View file
model_quantized.tflite ADDED
Binary file (34.9 kB). View file
net.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import tensorflow as tf
2
+ import tensorflow.keras.layers as layers
3
+
4
+ input_shape = (1,54,1)
5
+
6
+ model = tf.keras.models.Sequential()
7
+ model.add(layers.Conv1D(31, 7, activation='relu', input_shape=input_shape[1:]))
8
+ model.add(layers.MaxPooling1D(7, data_format='channels_first'))
9
+ model.add(layers.Conv1D(31, 7, activation='relu'))
10
+ model.add(layers.MaxPooling1D(7, data_format='channels_first'))
11
+ model.add(layers.Conv1D(31, 7, activation='relu'))
12
+ model.add(layers.MaxPooling1D(7, data_format='channels_first'))
13
+ model.add(layers.GRU(7))
14
+ model.add(layers.Dense(18))
15
+
16
+ model.compile(optimizer='sgd', loss='mse')
17
+
18
+ print("\n===============\n")
19
+
20
+ x = tf.random.normal(input_shape)
21
+ #print("x: ", x)
22
+
23
+ y = model.evaluate(x)
24
+ #print("y: ", y)
25
+
26
+ model = layers.Conv1D(31, 7, activation='relu', input_shape=input_shape[1:])(x)
27
+ print(model.shape)
28
+ model = layers.MaxPooling1D(7, data_format='channels_first')(model)
29
+ print(model.shape)
30
+ model = layers.Conv1D(31, 7, activation='relu')(model)
31
+ print(model.shape)
32
+ model = layers.MaxPooling1D(7, data_format='channels_first')(model)
33
+ print(model.shape)
34
+ model = layers.Conv1D(31, 7, activation='relu')(model)
35
+ print(model.shape)
36
+ model = layers.MaxPooling1D(7, data_format='channels_first')(model)
37
+ print(model.shape)
38
+ model = layers.GRU(7)(model)
39
+ print(model.shape)
40
+
overlays.txt ADDED
@@ -0,0 +1,2 @@
 
 
1
+ # List of device tree overlays to load. Format: overlay=<dtbo name, no extenstion> <dtbo2> ...
2
+ overlay=portiloop
portiloop.dts ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /dts-v1/;
2
+ /plugin/;
3
+
4
+ ///include/ "fsl-imx8mq-phanbell.dtb";
5
+
6
+ / {
7
+ compatible = "fsl,imx8mq-phanbell", "fsl,imx8mq";
8
+
9
+ fragment@0 {
10
+ target-path = "/hdmi@32c00000";
11
+ __overlay__ {
12
+ status = "disabled";
13
+ };
14
+ };
15
+
16
+ fragment@1 {
17
+ target-path = "/dcss@0x32e00000";
18
+ __overlay__ {
19
+ status = "disabled";
20
+ };
21
+ };
22
+
23
+ fragment@2 {
24
+ target-path = "/mipi_csi1@30a70000";
25
+ __overlay__ {
26
+ status = "disabled";
27
+ };
28
+ };
29
+
30
+ fragment@3 {
31
+ target-path = "/mipi_csi2@30b60000";
32
+ __overlay__ {
33
+ status = "disabled";
34
+ };
35
+ };
36
+
37
+ fragment@4 {
38
+ target-path = "/dsi_phy@30A00300";
39
+ __overlay__ {
40
+ status = "disabled";
41
+ };
42
+ };
43
+
44
+ fragment@5 {
45
+ target-path = "/mipi_dsi@30A00000";
46
+ __overlay__ {
47
+ status = "disabled";
48
+ };
49
+ };
50
+
51
+ fragment@6 {
52
+ target-path = "/csi1_bridge@30a90000";
53
+ __overlay__ {
54
+ status = "disabled";
55
+ };
56
+ };
57
+
58
+ fragment@7 {
59
+ target-path = "/sound-rt5645";
60
+ __overlay__ {
61
+ status = "disabled";
62
+ };
63
+ };
64
+
65
+ fragment@8 {
66
+ target-path = "/i2c@30a40000/rt5645@1a/";
67
+ __overlay__ {
68
+ status = "disabled";
69
+ };
70
+ };
71
+
72
+ fragment@9 {
73
+ target-path = "/i2c@30a30000";
74
+ __overlay__ {
75
+ status = "okay";
76
+
77
+ sgtl5000: audio-codec@a {
78
+ #sound-dai-cells = <0>;
79
+ compatible = "fsl,sgtl5000";
80
+ reg = <0x0a>;
81
+
82
+ clocks = <&clk IMX8MQ_CLK_SAI2_ROOT>;
83
+ assigned-clocks = <&clk IMX8MQ_CLK_SAI2>;
84
+ assigned-clock-parents = <&clk IMX8MQ_AUDIO_PLL1_OUT>;
85
+ assigned-clock-rates = <24576000>;
86
+
87
+ status = "okay";
88
+ };
89
+ };
90
+ };
91
+
92
+ fragment@a {
93
+ target-path = "/sai@308b0000";
94
+ __overlay__ {
95
+ #sound-dai-cells = <0>;
96
+ fsl,sai-mclk-direction-output;
97
+ };
98
+ };
99
+
100
+ fragment@b {
101
+ target-path = "/";
102
+ __overlay__ {
103
+ sound-sgtl5000 {
104
+ compatible = "simple-audio-card";
105
+
106
+ simple-audio-card,name = "sgtl5000";
107
+ simple-audio-card,format = "i2s";
108
+ simple-audio-card,widgets = "Headphone", "Headphones";
109
+ simple-audio-card,routing = "Headphones", "HPOUTL",
110
+ "Headphones", "HPOUTR";
111
+
112
+ status = "okay";
113
+
114
+ simple-audio-card,cpu {
115
+ sound-dai = <&sai2>;
116
+ };
117
+
118
+ audio_codec: simple-audio-card,codec {
119
+ sound-dai = <&sgtl5000>;
120
+ clocks = <&clk IMX8MQ_CLK_SAI2_ROOT>;
121
+ frame-master;
122
+ bitclock-master;
123
+ };
124
+ };
125
+ };
126
+ };
127
+
128
+ fragment@c {
129
+ target-path = "/dummy-dai";
130
+ __overlay__ {
131
+ status = "disabled";
132
+ };
133
+ };
134
+
135
+ fragment@d {
136
+ target-path = "/sound-header";
137
+ __overlay__ {
138
+ status = "disabled";
139
+ };
140
+ };
141
+ };
sample.mp3 ADDED
Binary file (291 kB). View file
shell.nix ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ with import <nixpkgs> {};
2
+ mkShell {
3
+ name = "tensorflow-cuda-shell";
4
+ buildInputs = with python3.pkgs; [
5
+ pip
6
+ setuptools
7
+ python39Packages.tensorflow
8
+ python39Packages.numpy
9
+ ];
10
+ shellHook = ''
11
+ export LD_LIBRARY_PATH=${pkgs.stdenv.cc.cc.lib}/lib:$LD_LIBRARY_PATH
12
+ alias pip="PIP_PREFIX='$(pwd)/_build/pip_packages' TMPDIR='$HOME' \pip"
13
+ export PYTHONPATH="$(pwd)/_build/pip_packages/lib/python3.7/site-packages:$PYTHONPATH"
14
+ export PATH="$(pwd)/_build/pip_packages/bin:$PATH"
15
+ unset SOURCE_DATE_EPOCH
16
+ '';
17
+ }