11 Commit

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

+ 1
- 0
weather-sensor/firmware/.gitignore Vedi File

@@ -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 Vedi File

@@ -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 Vedi File

@@ -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 Vedi File

@@ -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 Vedi File

@@ -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 Vedi File

@@ -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 Vedi File

@@ -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 Vedi File

@@ -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 Vedi File

@@ -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 Vedi File

@@ -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 Vedi File

@@ -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 Vedi File

@@ -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 Vedi File


+ 54
- 0
weather-sensor/firmware/pin_programming.c Vedi File

@@ -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 Vedi File

@@ -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 Vedi File

@@ -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

Loading…
Annulla
Salva