11 コミット

作成者 SHA1 メッセージ 日付
  Bernd Gottschlag 05696f7e74 Fix decryption bug 5年前
  Bernd Gottschlag 1381cb6634 Add encryption for the sent packet 5年前
  Bernd Gottschlag 3a21aef881 Rework the makefile and optimize the code for flash space 5年前
  Bernd Gottschlag 8a49c011c9 Update packet protocoll 5年前
  Bernd Gottschlag 58a48e5230 Fix order of the element count and packet type bit field 5年前
  Bernd Gottschlag e435620c91 Add a new packet format with the calculation of the CRC 5年前
  Bernd Gottschlag c86399b66e Add the calculation of a crc 5年前
  Bernd Gottschlag 30fe01bb9e Generate an ID according to the dip switches 5年前
  Bernd Gottschlag 3dcfae6196 Change the way the TX and RX addresses are written to the nrf24l01 5年前
  Bernd Gottschlag fa580c8af7 Add ToDos to the schematic 5年前
  Bernd Gottschlag e7bfca4363 Use the IRQ signal from the nrf24l01 instead of polling the status 5年前

+ 1
- 0
weather-sensor/firmware/.gitignore ファイルの表示

@@ -1,5 +1,6 @@
1 1
 main
2 2
 *.hex
3
+*.o
3 4
 
4 5
 
5 6
 *.swp

+ 2
- 0
weather-sensor/firmware/bme280_interface.c ファイルの表示

@@ -1,5 +1,6 @@
1 1
 #include <avr/io.h>
2 2
 #include <util/delay.h>
3
+#include <string.h>
3 4
 
4 5
 #include "spi.h"
5 6
 #include "bme280.h"
@@ -58,6 +59,7 @@ void Set_BME280_Pins(void)
58 59
 /* Get one measurement in forced mode */
59 60
 void BME280_Get_Measurement(struct bme280_data * data)
60 61
 {
62
+	memset(data, 0, sizeof(struct bme280_data));
61 63
 	bme280_set_sensor_mode(BME280_FORCED_MODE, &deviceStructure);
62 64
 	deviceStructure.delay_ms(req_delay);
63 65
 	bme280_get_sensor_data(BME280_ALL, data, &deviceStructure);

+ 53
- 0
weather-sensor/firmware/crc.c ファイルの表示

@@ -0,0 +1,53 @@
1
+#include <stdint.h>
2
+#include <avr/pgmspace.h>
3
+
4
+const uint16_t crcTable[256] PROGMEM =
5
+{
6
+	0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
7
+	0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
8
+	0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
9
+	0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
10
+	0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
11
+	0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
12
+	0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
13
+	0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
14
+	0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
15
+	0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
16
+	0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
17
+	0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
18
+	0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
19
+	0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
20
+	0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
21
+	0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
22
+	0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
23
+	0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
24
+	0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
25
+	0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
26
+	0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
27
+	0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
28
+	0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
29
+	0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
30
+	0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
31
+	0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
32
+	0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
33
+	0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
34
+	0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
35
+	0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
36
+	0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
37
+	0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
38
+};
39
+
40
+
41
+uint16_t Calculate_Crc(const uint8_t *buffer, uint8_t size)
42
+{
43
+	uint16_t crc = 0;
44
+	const uint8_t * tempPointer = buffer;
45
+
46
+	for (uint8_t i = 0; i < size; i++)
47
+	{
48
+		crc = (crc >> 8) ^ pgm_read_word(&crcTable[ (crc ^ (uint16_t) *tempPointer) & 0x00FF ]);
49
+		tempPointer++;
50
+	}
51
+
52
+	return crc;
53
+}

+ 5
- 0
weather-sensor/firmware/crc.h ファイルの表示

@@ -0,0 +1,5 @@
1
+#ifndef CRC_H
2
+#define CRC_H
3
+
4
+uint16_t Calculate_Crc(const uint8_t *buffer, uint8_t size);
5
+#endif

+ 118
- 0
weather-sensor/firmware/encryption.c ファイルの表示

@@ -0,0 +1,118 @@
1
+#include <stdint.h>
2
+
3
+#define LENGTH_OF_BLOCK 8
4
+
5
+void xxtea_Encrypt(uint32_t * data, uint8_t dataLength, const uint32_t key[4]);
6
+void xxtea_Decrypt(uint32_t * data, uint8_t dataLength, const uint32_t key[4]);
7
+
8
+/* The data packets are encrypted using the xxtea algorithm. */
9
+void Encrypt(uint32_t * data, uint8_t dataLength, uint64_t salt, const uint32_t key[4])
10
+{
11
+	/* This function assumes that the dataLength is a multiple of the length of the
12
+	 * salt (8)
13
+	 *
14
+	 * The data is encrypted using cipher block chaining:
15
+	 * (https://upload.wikimedia.org/wikipedia/commons/8/80/CBC_encryption.svg)
16
+	 */
17
+
18
+	uint8_t i;
19
+	uint8_t * previousCipherBlock = (uint8_t*) &salt;
20
+	uint8_t * currentPlaintextBlock = (uint8_t*) data;
21
+
22
+	for (i = 0; i < dataLength/LENGTH_OF_BLOCK; i++)
23
+	{
24
+		/* XOR of current plain text block and previous cipher block */
25
+		//for (j = 0; j < LENGTH_OF_BLOCK; j++)
26
+		//{
27
+		//	currentPlaintextBlock[j] ^= previousCipherBlock[j];
28
+		//}
29
+		*((uint64_t*) currentPlaintextBlock) ^= *((uint64_t*) previousCipherBlock);
30
+
31
+		/* Encrypt the block */
32
+		xxtea_Encrypt((uint32_t*) currentPlaintextBlock, LENGTH_OF_BLOCK, key);
33
+
34
+		/* Setup for next block */
35
+		previousCipherBlock = currentPlaintextBlock;
36
+		currentPlaintextBlock += LENGTH_OF_BLOCK;
37
+	}
38
+
39
+}
40
+
41
+
42
+void Decrypt(uint32_t * data, uint8_t dataLength, uint64_t salt, const uint32_t key[4])
43
+{
44
+	/* This function assumes that the dataLength is a multiple of the length of the
45
+	 * salt (8)
46
+	 *
47
+	 * The data is encrypted using cipher block chaining:
48
+	 * (https://upload.wikimedia.org/wikipedia/commons/2/2a/CBC_decryption.svg)
49
+	 */
50
+
51
+	/* The data is decrypted from back to front as front to back cannot be done in
52
+	 * place
53
+	 */
54
+	uint8_t i;
55
+	uint8_t * previousCipherBlock = (uint8_t*) data + dataLength - 2 * LENGTH_OF_BLOCK;
56
+	uint8_t * currentCipherBlock = (uint8_t*) data + dataLength - LENGTH_OF_BLOCK;
57
+
58
+	for (i = dataLength/LENGTH_OF_BLOCK; i > 0; i--)
59
+	{
60
+		/* Decrypt the block */
61
+		xxtea_Decrypt((uint32_t*) currentCipherBlock, LENGTH_OF_BLOCK, key);
62
+
63
+		/* XOR of the decrypted block with cipher block in front of it */
64
+		*((uint64_t*) currentCipherBlock) ^= *((uint64_t*) previousCipherBlock);
65
+
66
+		/* Setup for next block */
67
+		currentCipherBlock = previousCipherBlock;
68
+		if (previousCipherBlock != (uint8_t*) data + LENGTH_OF_BLOCK)
69
+		{
70
+			previousCipherBlock -= LENGTH_OF_BLOCK;
71
+		}
72
+		else
73
+		{
74
+			previousCipherBlock = (uint8_t*) &salt;
75
+		}
76
+	}
77
+}
78
+
79
+void xxtea_Encrypt(uint32_t * data, uint8_t dataLength, const uint32_t key[4])
80
+{
81
+    uint32_t sum = 0, z, y, e;
82
+    uint8_t i = 6 + 52/(dataLength/4), r;
83
+    const int16_t n = dataLength / 4 - 1;
84
+
85
+    z = data[n]; // left neighbour for the first round
86
+    do {
87
+        // cycle
88
+        sum += 0x9e3779b9ul;
89
+        e = (sum >> 2) & 3;
90
+        for (r = 0; r <= n; r++) {
91
+            // round
92
+            y = data[(r+1) % (n + 1)]; // right neighbour
93
+            data[r] += ((z>>5 ^ y<<2) + (y>>3 ^ z<<4)) ^ ((sum^y) + (key[(r^e) & 3] ^ z));
94
+            z = data[r]; // left neighbour for the next round
95
+        }
96
+    } while (--i);
97
+}
98
+
99
+void xxtea_Decrypt(uint32_t * data, uint8_t dataLength, const uint32_t key[4])
100
+{
101
+    uint32_t sum, z, y, e;
102
+    int16_t i = 6 + 52/(dataLength/4), r;
103
+    const int16_t n = dataLength / 4;
104
+
105
+    sum = (uint32_t) ((uint64_t) (6 + 52/(dataLength/4)) * 0x9e3779b9ul);
106
+    y = data[0];
107
+    do {
108
+        // cycle
109
+        e = sum >> 2;
110
+        for (r = n-1; r >= 0; --r) {
111
+            // round
112
+            z = data[(r+n-1) % n];
113
+            data[r] -= ((z>>5 ^ y<<2) + (y>>3 ^ z<<4)) ^ ((sum^y) + (key[(r^e) & 3] ^ z));
114
+            y = data[r];
115
+        }
116
+        sum -= 0x9e3779b9;
117
+    } while (--i);
118
+}

+ 8
- 0
weather-sensor/firmware/encryption.h ファイルの表示

@@ -0,0 +1,8 @@
1
+#ifndef ENCRYPTION_H
2
+#define ENCRYPTION_H
3
+
4
+
5
+void Encrypt(uint32_t * data, uint8_t dataLength , uint64_t salt, const uint32_t key[4]);
6
+void Decrypt(uint32_t * data, uint8_t dataLength, uint64_t salt, const uint32_t key[4]);
7
+
8
+#endif

+ 8
- 0
weather-sensor/firmware/led.h ファイルの表示

@@ -0,0 +1,8 @@
1
+#ifndef LED_H
2
+#define LED_H
3
+
4
+#define LED_DDR   DDRD
5
+#define LED_PORT  PORTD
6
+#define LED_PIN   PD3
7
+
8
+#endif

+ 63
- 24
weather-sensor/firmware/main.c ファイルの表示

@@ -6,20 +6,23 @@
6 6
 #include <stdio.h>
7 7
 #include <stdlib.h>
8 8
 #include <string.h>
9
+#include <stdbool.h>
9 10
 
11
+#include "led.h"
10 12
 #include "spi.h"
11 13
 #include "nrf24l01.h"
12 14
 #include "nrf24l01_definitions.h"
13 15
 #include "bme280_interface.h"
14 16
 #include "bme280_defs.h"
17
+#include "pin_programming.h"
18
+#include "crc.h"
19
+#include "encryption.h"
15 20
 
16 21
 
17 22
 
18
-/* Debug LED: */
19
-#define LED_DDR   DDRD
20
-#define LED_PORT  PORTD
21
-#define LED_PIN   PD3
22
-
23
+uint8_t ownId;
24
+const uint8_t encryptionKey[16] = {0x9e, 0x37, 0x79, 0xb9, 0x9b, 0x97, 0x73, 0xe9, 0xb9, 0x79, 0x37, 0x9e, 0x6b, 0x69, 0x51, 0x56}; /* TODO: use exernal file with the keys */
25
+uint64_t salt;
23 26
 
24 27
 char bool_case = 0;
25 28
 int timer = 0;
@@ -27,10 +30,16 @@ int timer_max = 0;
27 30
 
28 31
 volatile uint8_t cycle = 0;
29 32
 
33
+volatile bool nrfInterruptRaised;
34
+
30 35
 volatile uint8_t interruptCounter;
31 36
 volatile uint8_t executionFlag;
32 37
 
33 38
 
39
+
40
+static PACKET reportPacket;
41
+
42
+
34 43
 void Enter_Power_Save_Mode(void);
35 44
 void Exit_Power_Save_Mode(void);
36 45
 
@@ -50,23 +59,28 @@ void Set_Up_Power_Save_Mode(void);
50 59
 void Enter_Power_Save_Mode(void);
51 60
 
52 61
 
53
-ISR( TIMER2_COMPA_vect )
62
+ISR(TIMER2_COMPA_vect)
54 63
 {
55 64
 	/* Do nothing as the interrupt is only used to wake up the MCU. */
56 65
 }
57 66
 
67
+ISR(PCINT2_vect)
68
+{
69
+	nrfInterruptRaised = true;
70
+}
71
+
58 72
 int main (void)
59 73
 {
60 74
 	struct bme280_data sensorData;
61
-//	uint8_t testRegisterContent = 0x0A;
62
-//	uint8_t registerContent[5];
63
-//	char registerContentString[30];
64
-//	uint8_t lengthRead;
65
-	uint8_t temp = 0;
75
+	uint16_t crc;
66 76
 
67 77
 	/* Enable the debug LED */
68 78
 	LED_DDR |= (1 << LED_PIN);
69 79
 
80
+	/* Get the own ID */
81
+	Configure_Pin_Programming_Pins();
82
+	ownId = Get_Own_Identifier();
83
+
70 84
 	/* Initialize the SPI */
71 85
 	Initialize_SPI();
72 86
 
@@ -75,12 +89,15 @@ int main (void)
75 89
 	// The NRF24L01 is now in the mode Standby-I.
76 90
 
77 91
 	/* Configure the transmission parameters (Enhanced ShockBurst)*/
78
-	Configure_Transmission();
92
+	Configure_Transmission(ownId);
79 93
 
80 94
 	/* Initialize the BME280 */
81 95
 	Initialize_BME280();
82 96
 	Set_Up_Power_Save_Mode();
83 97
 
98
+	/* Initialize the salt */
99
+	salt = 0xFFFFFFFFFFFFFFFFull;
100
+	salt &= ~ownId;
84 101
 
85 102
 	/* Delay the change of the operating frequency by the function Enter_Power_Save_Mode for the
86 103
 	 * first function pass. If it is changed before the ISP can flash the MCU the clocks of the ISP
@@ -101,18 +118,40 @@ int main (void)
101 118
 
102 119
 			/* Get measurement and send it */
103 120
 			BME280_Get_Measurement(&sensorData);
104
-			NRF24L01_Send_Message((uint8_t*)&sensorData, sizeof(sensorData));
105
-
106
-			if (temp == 0)
107
-			{
108
-				LED_PORT |= (1 << LED_PIN);
109
-				temp = 1;
110
-			}
111
-			else
112
-			{
113
-				temp = 0;
114
-				LED_PORT &= ~(1 << LED_PIN);
115
-			}
121
+
122
+
123
+			memset((uint8_t*)&reportPacket, 0, sizeof(reportPacket)); //Reinitialize the buffer with zeros
124
+
125
+			salt &= ~(1ull<<55);
126
+			reportPacket.salt = salt;
127
+			reportPacket.payload.values.packetIdentifier.elementCount = 3;
128
+			reportPacket.payload.values.packetIdentifier.packetType = PACKET_TYPE_REPORT;
129
+
130
+			/* Fill in the payload */
131
+			reportPacket.payload.values.valueTypeTemperature = VALUE_TYPE_TEMPERATURE;
132
+			reportPacket.payload.values.temperature = sensorData.temperature/10;
133
+			reportPacket.payload.values.valueTypePressure = VALUE_TYPE_PRESSURE;
134
+			reportPacket.payload.values.pressure = sensorData.pressure;
135
+			reportPacket.payload.values.valueTypeHumidity = VALUE_TYPE_HUMIDITY;
136
+			reportPacket.payload.values.humidity = sensorData.humidity * 100/1024;
137
+
138
+			/* Calculate the CRC */
139
+			crc = Calculate_Crc(reportPacket.payload.buffer, PACKET_BUFFER_LENGTH);
140
+			reportPacket.crc = crc;
141
+
142
+			/* Encrypt the packet */
143
+			/* TODO: 
144
+			 * - increment the salt for every packet
145
+			 * - Receive salt from the base station
146
+			 */
147
+			Encrypt((uint32_t*) &reportPacket.payload.buffer,
148
+			        PACKET_BUFFER_LENGTH + sizeof(crc),
149
+			        salt, (uint32_t*) encryptionKey);
150
+
151
+			NRF24L01_Send_Message((uint8_t*)&reportPacket, sizeof(reportPacket));
152
+
153
+			_delay_ms(100); /* TODO: only for debugging, remove this later! */
154
+			LED_PORT &= ~(1 << LED_PIN);
116 155
 
117 156
 			cycle = 0;
118 157
 		}

+ 13
- 3
weather-sensor/firmware/makefile ファイルの表示

@@ -1,14 +1,24 @@
1
+CFLAGS = -DF_CPU=1000000UL -D BME280_32BIT_ENABLE -I BME280_driver -mmcu=atmega88p -Os -flto -Wall -Wextra -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
2
+DEPS = spi.h nrf24l01.h nrf24l01_definitions.h bme280_interface.h BME280_driver/bme280.h led.h pin_programming.h crc.h encryption.h
3
+
1 4
 all: main.hex
2 5
 
3 6
 clean:
4 7
 	rm -f main.hex
5 8
 	rm -f main
9
+	rm -f obj/*.o
6 10
 
7 11
 flash: main.hex
8
-	sudo avrdude -c buspirate -b 115200 -P /dev/ttyUSB0 -p m88p -v -U flash:w:main.hex
12
+	sudo avrdude -c buspirate -b 115200 -P /dev/ttyUSB1 -p m88p -v -U flash:w:main.hex
13
+
14
+obj/%.o: %.c $(DEPS)
15
+	avr-gcc -c $< -o $@ $(CFLAGS)
16
+
17
+obj/%.o: BME280_driver/%.c $(DEPS)
18
+	avr-gcc -c $< -o $@ $(CFLAGS)
9 19
 
10
-main: main.c spi.c spi.h nrf24l01.c nrf24l01.h nrf24l01_definitions.h bme280_interface.c bme280_interface.h BME280_driver/bme280.c BME280_driver/bme280.h
11
-	avr-gcc main.c spi.c nrf24l01.c bme280_interface.c BME280_driver/bme280.c -I BME280_driver -o main -mmcu=atmega88p -Os -Wall -Wextra -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -DF_CPU=1000000UL -D BME280_32BIT_ENABLE
20
+main: obj/main.o obj/spi.o obj/nrf24l01.o obj/bme280_interface.o obj/bme280.o obj/pin_programming.o obj/crc.o obj/encryption.o
21
+	avr-gcc $^ -o $@ $(CFLAGS)
12 22
 
13 23
 main.hex: main
14 24
 	avr-objcopy -O ihex -R .eeprom main main.hex

+ 65
- 122
weather-sensor/firmware/nrf24l01.c ファイルの表示

@@ -4,20 +4,24 @@
4 4
 #include <stdio.h>
5 5
 #include <stdbool.h>
6 6
 
7
+#include "led.h" // TODO: for debugging
7 8
 #include "spi.h"
8 9
 #include "nrf24l01.h"
9 10
 #include "nrf24l01_definitions.h"
10 11
 
11 12
 /* TODO
12
- * - Build a state machine that tracks the mode the NRF is set to
13
- * - Configuration of NRF24L01 and startup
14
- * - Send and Receive functions
15
- * - Interrupt handling for Send and Receive
13
+ * - Send functions
14
+ * - Interrupt handling for Send
16 15
  */
17 16
 
17
+extern volatile bool nrfInterruptRaised;
18
+
18 19
 void Print_Register_Contents(uint8_t address);
19 20
 void Send_TX_Flush_Command(void);
20 21
 
22
+static void Write_Two_Bytes(uint8_t byte1, uint8_t byte2);
23
+static void Write_Byte_And_Buffer(uint8_t byte, uint8_t * buffer, uint8_t length);
24
+
21 25
 /* Startup and initial configuration of the NRF24L01 */
22 26
 void Initialize_NRF24L01(void)
23 27
 {
@@ -51,13 +55,21 @@ void Set_NRF24L01_Pins(void)
51 55
 
52 56
 	/* Ensure that the CE pin is set to 0*/
53 57
 	NRF_CE_PORT &= ~(1 << NRF_CE_PIN);
58
+
59
+	/* Set the interrupt pin */
60
+	/* TODO: PCINT21 -> PCINT2 */
61
+	NRF_IRQ_DDR &= ~(1 << NRF_IRQ_PIN); // Set the pin as input
62
+	NRF_IRQ_PORT |= (1 << NRF_IRQ_PORT); // Enable the pullup for the pin
54 63
 }
55 64
 
56
-void Configure_Transmission(void)
65
+void Configure_Transmission(uint8_t moduleId)
57 66
 {
58 67
 	FEATURE_REGISTER featureRegisterContents = {.byte = 0x0};
59 68
 	DYNPD_REGISTER dyndpRegisterContents = {.byte = 0x0};
60 69
 	SETUP_RETR_REGISTER setupRetrRegisterContents = {.byte = 0x0};
70
+
71
+	uint8_t txAddress[5] = {0xB3, 0xB3, 0xB3, 0xB3, 0x00};
72
+	uint8_t rx0Address[5] = {0xB3, 0xB3, 0xB3, 0xB3, 0x20};
61 73
 	/* 
62 74
 	 * - Length of CRC (CRCO in CONFIG)
63 75
 	 * - Enable auto acknowledgment (EN_AA)
@@ -93,7 +105,7 @@ void Configure_Transmission(void)
93 105
 	setupRetrRegisterContents.bits.ARD = 0xF;
94 106
 	Write_NRF_Register(SETUP_RETR_ADDRESS, setupRetrRegisterContents.byte);
95 107
 
96
-	/* set dynamic payload length for all data pipes */
108
+	/* set dynamic payload length for all data pipes */ // TODO: only pipe 0 is currently in use -> don't set the other values
97 109
 	dyndpRegisterContents.bits.DPL_P0 = 1;
98 110
 	dyndpRegisterContents.bits.DPL_P1 = 1;
99 111
 	dyndpRegisterContents.bits.DPL_P2 = 1;
@@ -103,35 +115,26 @@ void Configure_Transmission(void)
103 115
 	Write_NRF_Register(DYNPD_ADDRESS, dyndpRegisterContents.byte);
104 116
 
105 117
 	/* Set the TX address */
106
-	Set_TX_Address(0x123456);
118
+	Set_TX_Address(txAddress, MAX_ADDRESS_LENGTH);
107 119
 
108
-	Set_RX_P0_Address(0x123456);
109
-	
120
+	rx0Address[4] = moduleId; // The last byte of the address corresponds to the Id set by the pin programming
121
+	Set_RX_P0_Address(rx0Address, MAX_ADDRESS_LENGTH);
110 122
 
111
-	// TODO: set addresses for all data pipes
123
+
124
+	PCMSK2 |= (1<<PCINT21); // Set the external interrupt for PD5
112 125
 }
113 126
 
114 127
 void NRF24L01_Send_Message(uint8_t *buffer, uint8_t length)
115 128
 {
116
-	bool transmissionFinished = false;
117
-
118 129
 	STATUS_REGISTER statusRegisterContents = {.byte = 0x0};
119
-	uint32_t timeout = 0;
120
-	/* TODO:
121
-	 * - if needed: PRIM_RX = 0
122
-	 * - Set CE = 1 for more than 10 us
123
-	 * - Wait until the transmission is finished
124
-	 * - Read number of retries for debug purposes
125
-	 * - Check if the FIFO is empty -> if not, flush it
126
-	 * - reset the interupts of the STATUS
127
-	 */
128 130
 	
129
-	/* TODO: messages with more than 32 byte length */
130 131
 	if ((length > 32) || (length == 0))
131 132
 	{
132 133
 		return;
133 134
 	}
134 135
 
136
+	PCICR |= (1<<PCIE2); // Enable the interrupt for the IRQ signal
137
+
135 138
 	Write_Message_To_TX_FIFO(length, buffer);
136 139
 
137 140
 	/* Set CE = 1 for more than 10 us */
@@ -139,73 +142,35 @@ void NRF24L01_Send_Message(uint8_t *buffer, uint8_t length)
139 142
 	_delay_us(15);
140 143
 	NRF_CE_PORT &= ~(1 << NRF_CE_PIN);
141 144
 
145
+	while (nrfInterruptRaised == false); // Wait until the transmission is complete
146
+	/* An interrupt instead of polling the status register is used to avoid transmission errors
147
+	 * induced by the SPI:
148
+	 * https://forum.mysensors.org/topic/10452/nrf24l01-communication-failure-root-cause-and-solution
149
+	 */
150
+	LED_PORT |= (1 << LED_PIN);
151
+
152
+	statusRegisterContents.byte = Read_NRF_Status_Register();
153
+
142 154
 
143
-	do
155
+	if (statusRegisterContents.bits.MAX_RT == 1)
144 156
 	{
145
-		_delay_ms(1);
146
-		/* TODO: instead of polling the status register use the IRQ to spawn an interrupt as the
147
-		 * constant polling may induce transmission errors:
148
-		 * https://forum.mysensors.org/topic/10452/nrf24l01-communication-failure-root-cause-and-solution
149
-		 */
150
-		statusRegisterContents.byte = Read_NRF_Status_Register();
151
-
152
-		if (statusRegisterContents.bits.TX_DS == 1)
153
-		{
154
-			transmissionFinished = true;
155
-		}
156
-
157
-		if (statusRegisterContents.bits.MAX_RT == 1)
158
-		{
159
-			transmissionFinished = true; //TODO: indicate failure
160
-
161
-			Send_TX_Flush_Command(); /* Remove the packet from the TX FIFO as it is not done automatically */
162
-		}
163
-		
164
-		timeout ++; // TODO: this should work without the time out, as MAX_RT should be triggered if no ACK is received
165
-	} while ((transmissionFinished == false) && (timeout < 0xFF));
157
+		Send_TX_Flush_Command(); /* Remove the packet from the TX FIFO as it is not done automatically */
158
+	}
159
+	
166 160
 
167 161
 	/* Reset the interrupts */
168
-	statusRegisterContents.byte = Read_NRF_Status_Register();
169 162
 	statusRegisterContents.bits.TX_DS = 1;
170 163
 	statusRegisterContents.bits.MAX_RT = 1;
164
+	statusRegisterContents.bits.RX_DR = 1;
171 165
 	Write_NRF_Register(STATUS_ADDRESS, statusRegisterContents.byte);
172
-}
173
-
174
-void Print_Register_Contents(uint8_t address)
175
-{
176
-	uint8_t registerContent[5];
177
-	uint8_t lengthRead;
178
-	char registerContentString[30];
179 166
 
167
+	PCICR &= ~(1<<PCIE2); // Disable the interrupt for the IRQ signal
168
+	nrfInterruptRaised = false;
180 169
 
181
-	lengthRead = Read_NRF_Register(address, registerContent);
182 170
 
183
-	registerContentString[0] = '\0';
184
-	for (uint8_t i = 0; i < lengthRead; i++)
185
-	{
186
-		sprintf(registerContentString, "%s0x%x ", registerContentString, registerContent[i]);
187
-	}
171
+	return;
188 172
 }
189 173
 
190
-
191
-
192
-
193
-/* Send a message:
194
- * - Set PRIM_RX = 0 and add one message to the TX-FIFO
195
- * - Set CE=1 for more than 10 us
196
- * - The NRF takes 130 us to enter the TX Mode
197
- * - An Interrupt is generated once the 
198
- * - 
199
- */
200
-
201
-
202
-/* Set the NRF to RX Mode */
203
-
204
-/* Disable the RX Mode */
205
-
206
-
207
-
208
-
209 174
 uint8_t Read_NRF_Status_Register(void)
210 175
 {
211 176
 	uint8_t registerContents;
@@ -216,6 +181,9 @@ uint8_t Read_NRF_Status_Register(void)
216 181
 	return registerContents;
217 182
 }
218 183
 
184
+
185
+/* TODO: rewrite the read register function if it is needed (remove the read operations for the 5-byte registers)*/
186
+#if 0
219 187
 uint8_t Read_NRF_Register(uint8_t address, uint8_t * registerContents)
220 188
 {
221 189
 	/* TODO: simplify this function, as the registers with more than one byte are accessed with other functions */
@@ -250,28 +218,24 @@ uint8_t Read_NRF_Register(uint8_t address, uint8_t * registerContents)
250 218
 	return numberOfBytes;
251 219
 }
252 220
 
221
+#endif
222
+
253 223
 void Write_NRF_Register(uint8_t address, uint8_t registerContents)
254 224
 {
255
-	/* First write the write command with the address */
256
-	SPI_Start_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN);
257
-
258
-	SPI_Transfer_Byte(address | 0x20);
259
-
260
-	/* Write the data byte */
261
-	SPI_Transfer_Byte(registerContents);
262
-
263
-	SPI_Stop_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN);
225
+	Write_Two_Bytes(address | 0x20, registerContents);
264 226
 }
265 227
 
266
-// TODO: clean up functions
267 228
 void Send_Activate_Command(void)
268 229
 {
269
-	/* First write the write command with the address */
230
+	Write_Two_Bytes(0x50, 0x73);
231
+}
232
+
233
+static void Write_Two_Bytes(uint8_t byte1, uint8_t byte2)
234
+{
270 235
 	SPI_Start_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN);
271
-	SPI_Transfer_Byte(0x50);
272 236
 
273
-	/* Write the data byte */
274
-	SPI_Transfer_Byte(0x73);
237
+	SPI_Transfer_Byte(byte1);
238
+	SPI_Transfer_Byte(byte2);
275 239
 
276 240
 	SPI_Stop_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN);
277 241
 }
@@ -290,51 +254,30 @@ void Send_TX_Flush_Command(void)
290 254
 
291 255
 void Write_Message_To_TX_FIFO(uint8_t length, uint8_t * buffer)
292 256
 {
293
-	SPI_Start_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN);
294
-
295
-	/* Issue the write command: */
296
-	SPI_Transfer_Byte(0xA0);
297
-
298
-	/* Write the data bytes */
299
-	for (uint8_t i = 0; i < length; i++)
300
-	{
301
-		SPI_Transfer_Byte(buffer[i]);
302
-	}
303
-
304
-	SPI_Stop_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN);
257
+	Write_Byte_And_Buffer(0xA0, buffer, length);
305 258
 }
306 259
 
307
-void Set_TX_Address(uint32_t txAddress)
260
+void Set_TX_Address(uint8_t * txAddress, uint8_t length)
308 261
 {
309
-	uint8_t * buffer = (uint8_t*) &txAddress;
310
-
311
-	SPI_Start_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN);
312
-
313
-	SPI_Transfer_Byte(TX_ADDR_ADDRESS | 0x20);
314
-	/* Write the data byte */
315
-	for (uint8_t i = 0; i < 4; i ++)
316
-	{
317
-		SPI_Transfer_Byte(buffer[i]);
318
-	}
319
-	SPI_Transfer_Byte(0x0);
320
-
321
-	SPI_Stop_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN);
262
+	Write_Byte_And_Buffer(TX_ADDR_ADDRESS | 0x20, txAddress, length);
322 263
 }
323 264
 
324
-void Set_RX_P0_Address(uint32_t rxAddress)
265
+void Set_RX_P0_Address(uint8_t * rxAddress, uint8_t length)
325 266
 {
326
-	uint8_t * buffer = (uint8_t*) &rxAddress;
267
+	Write_Byte_And_Buffer(RX_ADDR_P0_ADDRESS | 0x20, rxAddress, length);
268
+}
327 269
 
270
+static void Write_Byte_And_Buffer(uint8_t byte, uint8_t * buffer, uint8_t length)
271
+{
328 272
 	SPI_Start_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN);
329 273
 
330
-	SPI_Transfer_Byte(RX_ADDR_P0_ADDRESS | 0x20);
274
+	SPI_Transfer_Byte(byte);
331 275
 
332 276
 	/* Write the data byte */
333
-	for (uint8_t i = 0; i < 4; i ++)
277
+	for (uint8_t i = 0; i < length; i ++)
334 278
 	{
335 279
 		SPI_Transfer_Byte(buffer[i]);
336 280
 	}
337
-	SPI_Transfer_Byte(0x0);
338 281
 
339 282
 	SPI_Stop_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN);
340 283
 }

+ 51
- 7
weather-sensor/firmware/nrf24l01.h ファイルの表示

@@ -1,7 +1,7 @@
1 1
 #ifndef NRF24L01_H
2 2
 #define NRF24L01_H
3 3
 
4
-
4
+#define PACKET_BUFFER_LENGTH 22
5 5
 
6 6
 /* AVR I/O pin definionts */
7 7
 #define NRF_CE_DDR   DDRD
@@ -12,13 +12,15 @@
12 12
 #define NRF_CSN_PORT  PORTD
13 13
 #define NRF_CSN_PIN   PD6
14 14
 
15
-#define NRF_IRQ_DDR   DDRD
16
-#define NRF_IRQ_PORT  PORTD
17
-#define NRF_IRQ_PIN   PD5
15
+#define NRF_IRQ_DDR     DDRD
16
+#define NRF_IRQ_PORT    PORTD
17
+#define NRF_IRQ_PIN     PD5
18
+#define NRF_IRQ_PORTIN  PIND
19
+
18 20
 
19 21
 void Initialize_NRF24L01(void);
20 22
 void Set_NRF24L01_Pins(void);
21
-void Configure_Transmission(void);
23
+void Configure_Transmission(uint8_t moduleId);
22 24
 uint8_t Read_NRF_Status_Register(void);
23 25
 uint8_t Read_NRF_Register(uint8_t address, uint8_t * registerContents);
24 26
 void Write_NRF_Register(uint8_t address, uint8_t registerContents);
@@ -26,7 +28,49 @@ void Send_Activate_Command(void);
26 28
 
27 29
 void NRF24L01_Send_Message(uint8_t *buffer, uint8_t length);
28 30
 void Write_Message_To_TX_FIFO(uint8_t length, uint8_t * buffer);
29
-void Set_TX_Address(uint32_t txAddress);
30
-void Set_RX_P0_Address(uint32_t rxAddress);
31
+void Set_TX_Address(uint8_t * txAddress, uint8_t length);
32
+void Set_RX_P0_Address(uint8_t * rxAddress, uint8_t length);
33
+
34
+typedef enum
35
+{
36
+	PACKET_TYPE_SALT = 0,
37
+	PACKET_TYPE_REPORT = 1,
38
+	PACKET_TYPE_GET_VALUES = 2,
39
+	PACKET_TYPE_VALUES = 3,
40
+} PACKET_TYPE;
41
+
42
+typedef enum
43
+{
44
+	VALUE_TYPE_TIME = 0,
45
+	VALUE_TYPE_TEMPERATURE = 1,
46
+	VALUE_TYPE_PRESSURE = 2,
47
+	VALUE_TYPE_HUMIDITY = 3,
48
+} VALUE_TYPES;
49
+
50
+typedef struct __attribute__((packed)) BITFIELD_PACKET_COUNT_ELEMENT
51
+{
52
+	uint8_t packetType : 5;
53
+	uint8_t elementCount : 3;
54
+} BITFIELD_PACKET_COUNT_ELEMENT;
55
+
56
+typedef struct __attribute__((packed)) PACKET
57
+{
58
+	uint64_t salt; /* 1 byte device id, 7 bytes remainder */
59
+	union {
60
+		struct {
61
+			BITFIELD_PACKET_COUNT_ELEMENT packetIdentifier;
62
+			uint8_t valueTypeTemperature;
63
+			int16_t temperature;
64
+			uint8_t valueTypePressure;
65
+			uint32_t pressure;
66
+			uint8_t valueTypeHumidity;
67
+			uint16_t humidity;
68
+			uint8_t unused[10];
69
+		} values;
70
+		uint8_t buffer[PACKET_BUFFER_LENGTH];
71
+	}payload;
72
+	uint16_t crc;
73
+} PACKET;
74
+
31 75
 
32 76
 #endif

+ 1
- 0
weather-sensor/firmware/nrf24l01_definitions.h ファイルの表示

@@ -1,6 +1,7 @@
1 1
 #ifndef NRF24L01_DEFINITIONS_H
2 2
 #define NRF24L01_DEFINITIONS_H
3 3
 
4
+#define MAX_ADDRESS_LENGTH 5
4 5
 
5 6
 /* NRF24L01 register mnemonic definitions */
6 7
 #define CONFIG_ADDRESS 0x0

+ 0
- 0
weather-sensor/firmware/obj/.keep ファイルの表示


+ 54
- 0
weather-sensor/firmware/pin_programming.c ファイルの表示

@@ -0,0 +1,54 @@
1
+#include <avr/io.h>
2
+#include <stdint.h>
3
+
4
+#include "pin_programming.h"
5
+
6
+/* Pin definitions */
7
+
8
+
9
+#define PIN_PROG_1_DDR     DDRB
10
+#define PIN_PROG_1_PORT    PORTB
11
+#define PIN_PROG_1_PIN     PB6
12
+#define PIN_PROG_1_PORTIN  PINB
13
+
14
+#define PIN_PROG_2_DDR     DDRB
15
+#define PIN_PROG_2_PORT    PORTB
16
+#define PIN_PROG_2_PIN     PB7
17
+#define PIN_PROG_2_PORTIN  PINB
18
+
19
+#define PIN_PROG_3_DDR     DDRD
20
+#define PIN_PROG_3_PORT    PORTD
21
+#define PIN_PROG_3_PIN     PD4
22
+#define PIN_PROG_3_PORTIN  PIND
23
+
24
+
25
+
26
+void Configure_Pin_Programming_Pins(void)
27
+{
28
+	/* Set pins as input */
29
+	PIN_PROG_1_DDR &= ~(1 << PIN_PROG_1_PIN);
30
+	PIN_PROG_2_DDR &= ~(1 << PIN_PROG_2_PIN);
31
+	PIN_PROG_3_DDR &= ~(1 << PIN_PROG_3_PIN);
32
+
33
+	/* Enable pull-ups */ // TODO: enable once the boards have been fixed!
34
+	PIN_PROG_1_PORT |= (1 << PIN_PROG_1_PIN);
35
+	PIN_PROG_2_PORT |= (1 << PIN_PROG_2_PIN);
36
+	PIN_PROG_3_PORT |= (1 << PIN_PROG_3_PIN);
37
+}
38
+
39
+uint8_t Get_Own_Identifier(void)
40
+{
41
+	/* The upper four bits of the ID are the module ID while the lower four bits are the serial
42
+	 * number set by the pin programming.
43
+	 * Switch 3 corresponds to bit 0
44
+	 * Switch 2 corresponds to bit 1
45
+	 * Switch 1 corresponds to bit 2
46
+	 */
47
+	uint8_t id = (MODULE_ID_SENSOR << 4);
48
+
49
+	id |= ((((PIN_PROG_3_PORTIN & (1 << PIN_PROG_3_PIN)) == 0) << 0) | \
50
+	       (((PIN_PROG_2_PORTIN & (1 << PIN_PROG_2_PIN)) == 0) << 1) | \
51
+	       (((PIN_PROG_1_PORTIN & (1 << PIN_PROG_1_PIN)) == 0) << 2));
52
+
53
+	return id;
54
+}

+ 13
- 0
weather-sensor/firmware/pin_programming.h ファイルの表示

@@ -0,0 +1,13 @@
1
+#ifndef PIN_PROGRAMMING_H
2
+#define PIN_PROGRAMMING_H
3
+
4
+typedef enum
5
+{
6
+	MODULE_ID_BASE_STATION = 1,
7
+	MODULE_ID_DISPLAY      = 2,
8
+	MODULE_ID_SENSOR       = 3
9
+} MODULE_ID;
10
+
11
+void Configure_Pin_Programming_Pins(void);
12
+uint8_t Get_Own_Identifier(void);
13
+#endif

+ 5
- 1
weather-sensor/hardware/weather_station_sensor.sch ファイルの表示

@@ -914,7 +914,7 @@ LED
914 914
 Wire Wire Line
915 915
 	6050 4500 6150 4500
916 916
 Text Notes 2850 7250 0    50   ~ 0
917
-TODO: other diode in 0603 package
917
+TODO: change diode to 0804 package
918 918
 $Comp
919 919
 L Device:D_Zener D1
920 920
 U 1 1 5E5B4A6A
@@ -941,4 +941,8 @@ F 5 "https://www.digikey.com/products/en?keywords=587-5869-1-ND%20" H 3700 6300
941 941
 	1    3700 6300
942 942
 	1    0    0    -1  
943 943
 $EndComp
944
+Text Notes 7350 6250 0    50   ~ 0
945
+TODO: connect pins 4,5,6 to\nground instead of vcc
946
+Text Notes 9600 1600 0    50   ~ 0
947
+TODO: remove copper plating in the\nradiation direction of the antenna
944 948
 $EndSCHEMATC

読み込み中…
キャンセル
保存