8 Коміти

Автор SHA1 Повідомлення Дата
  Bernd Gottschlag 9cc2488996 Put send functions into a separate file 5 роки тому
  Bernd Gottschlag 4f83ec8bef Add handling of the salt 5 роки тому
  Bernd Gottschlag b31efd8359 Fix decryption function 5 роки тому
  Bernd Gottschlag 08546c2e36 Re-enable dynamic packet length 5 роки тому
  Bernd Gottschlag fe5cd5fc86 Add delay after setting the pull ups for pin programming 5 роки тому
  Bernd Gottschlag 9694fa3913 Fix the rx0 address 5 роки тому
  Bernd Gottschlag f78e2f65c6 Disable the dynamic packet length 5 роки тому
  Bernd Gottschlag 608a6ee253 Fix generation of the salt 5 роки тому

+ 1
- 1
weather-sensor/firmware/encryption.c Переглянути файл

@@ -65,7 +65,7 @@ void Decrypt(uint32_t * data, uint8_t dataLength, uint64_t salt, const uint32_t
65 65
 
66 66
 		/* Setup for next block */
67 67
 		currentCipherBlock = previousCipherBlock;
68
-		if (previousCipherBlock != (uint8_t*) data + LENGTH_OF_BLOCK)
68
+		if (previousCipherBlock != (uint8_t*) data)
69 69
 		{
70 70
 			previousCipherBlock -= LENGTH_OF_BLOCK;
71 71
 		}

+ 37
- 49
weather-sensor/firmware/main.c Переглянути файл

@@ -15,13 +15,11 @@
15 15
 #include "bme280_interface.h"
16 16
 #include "bme280_defs.h"
17 17
 #include "pin_programming.h"
18
-#include "crc.h"
19
-#include "encryption.h"
18
+#include "radio.h"
20 19
 
21 20
 
22 21
 
23 22
 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 23
 uint64_t salt;
26 24
 
27 25
 char bool_case = 0;
@@ -36,25 +34,15 @@ volatile uint8_t interruptCounter;
36 34
 volatile uint8_t executionFlag;
37 35
 
38 36
 
39
-
40
-static PACKET reportPacket;
37
+static uint8_t messageBuffer[PACKET_LENGTH];
38
+static PACKET * packet = (PACKET*) messageBuffer;
41 39
 
42 40
 
43 41
 void Enter_Power_Save_Mode(void);
44 42
 void Exit_Power_Save_Mode(void);
45 43
 
46 44
 
47
-/* TODO Notes for power saving:
48
- * - Power-save-mode needed -> SM2...0 bits written to 011
49
- * - Entering by issuing the SLEEP instruction -> What call in C?
50
- *   - Before executing the SLEEP instruction, write bit SE of the SMCR to 1
51
- * - Let Timer/Counter2 run with the necessary period and enable an interrupt.
52
- *   -> The Global Interrupt Enable bit in SREG has to be set.
53
- * - asynchronous/synchronous clock source?
54
- * - When waking up
55
- *   - Set PRR bits for needed peripherals
56
- * - 
57
- */
45
+
58 46
 void Set_Up_Power_Save_Mode(void);
59 47
 void Enter_Power_Save_Mode(void);
60 48
 
@@ -72,7 +60,7 @@ ISR(PCINT2_vect)
72 60
 int main (void)
73 61
 {
74 62
 	struct bme280_data sensorData;
75
-	uint16_t crc;
63
+	bool saltReceived = false;
76 64
 
77 65
 	/* Enable the debug LED */
78 66
 	LED_DDR |= (1 << LED_PIN);
@@ -96,8 +84,34 @@ int main (void)
96 84
 	Set_Up_Power_Save_Mode();
97 85
 
98 86
 	/* Initialize the salt */
99
-	salt = 0xFFFFFFFFFFFFFFFFull;
100
-	salt &= ~ownId;
87
+	salt = 0x0ull;
88
+	salt |= ownId;
89
+
90
+
91
+	/* Request a salt from the base station */
92
+	LED_PORT |= (1 << LED_PIN);
93
+	do
94
+	{
95
+		if (Send_Get_Salt_Message(packet, &salt) == true)
96
+		{
97
+			memset(messageBuffer, 0x0F, 32);
98
+			if (NRF24L01_Receive_Message(messageBuffer, 100 /*ms*/) == true)
99
+			{
100
+				_delay_ms(10);
101
+				saltReceived = Read_Salt_Message(packet, &salt);
102
+			}
103
+		}
104
+		else
105
+		{
106
+			/* TODO: enter power save mode instead to make the battery life longer */
107
+			_delay_ms(100);
108
+		}
109
+	} while (saltReceived == false);
110
+	LED_PORT &= ~(1 << LED_PIN);
111
+
112
+	salt &= 0xFFFFFFFFFFFFFF00ull;
113
+	salt |= ownId;
114
+
101 115
 
102 116
 	/* Delay the change of the operating frequency by the function Enter_Power_Save_Mode for the
103 117
 	 * first function pass. If it is changed before the ISP can flash the MCU the clocks of the ISP
@@ -119,37 +133,10 @@ int main (void)
119 133
 			/* Get measurement and send it */
120 134
 			BME280_Get_Measurement(&sensorData);
121 135
 
136
+			/* Send the report */
137
+			Send_Report_Message(packet, &salt, &sensorData);
122 138
 
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
-
139
+			LED_PORT |= (1 << LED_PIN);
153 140
 			_delay_ms(100); /* TODO: only for debugging, remove this later! */
154 141
 			LED_PORT &= ~(1 << LED_PIN);
155 142
 
@@ -225,3 +212,4 @@ void Exit_Power_Save_Mode(void)
225 212
 	PRR &= ~(1<<PRSPI); // Enable SPI
226 213
 	Initialize_SPI(); // reinitalize SPI
227 214
 }
215
+

+ 3
- 3
weather-sensor/firmware/makefile Переглянути файл

@@ -1,5 +1,5 @@
1 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
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 radio.h
3 3
 
4 4
 all: main.hex
5 5
 
@@ -9,7 +9,7 @@ clean:
9 9
 	rm -f obj/*.o
10 10
 
11 11
 flash: main.hex
12
-	sudo avrdude -c buspirate -b 115200 -P /dev/ttyUSB1 -p m88p -v -U flash:w:main.hex
12
+	sudo avrdude -c buspirate -b 115200 -P /dev/ttyUSB0 -p m88p -v -U flash:w:main.hex
13 13
 
14 14
 obj/%.o: %.c $(DEPS)
15 15
 	avr-gcc -c $< -o $@ $(CFLAGS)
@@ -17,7 +17,7 @@ obj/%.o: %.c $(DEPS)
17 17
 obj/%.o: BME280_driver/%.c $(DEPS)
18 18
 	avr-gcc -c $< -o $@ $(CFLAGS)
19 19
 
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
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 obj/radio.o
21 21
 	avr-gcc $^ -o $@ $(CFLAGS)
22 22
 
23 23
 main.hex: main

+ 163
- 75
weather-sensor/firmware/nrf24l01.c Переглянути файл

@@ -17,9 +17,13 @@
17 17
 extern volatile bool nrfInterruptRaised;
18 18
 
19 19
 void Print_Register_Contents(uint8_t address);
20
+
21
+
20 22
 void Send_TX_Flush_Command(void);
23
+void Send_RX_Flush_Command(void);
21 24
 
22
-static void Write_Two_Bytes(uint8_t byte1, uint8_t byte2);
25
+static uint8_t Write_One_Byte(uint8_t byte1);
26
+static uint8_t Write_Two_Bytes(uint8_t byte1, uint8_t byte2);
23 27
 static void Write_Byte_And_Buffer(uint8_t byte, uint8_t * buffer, uint8_t length);
24 28
 
25 29
 /* Startup and initial configuration of the NRF24L01 */
@@ -64,33 +68,15 @@ void Set_NRF24L01_Pins(void)
64 68
 
65 69
 void Configure_Transmission(uint8_t moduleId)
66 70
 {
71
+	SETUP_RETR_REGISTER setupRetrRegisterContents = {.byte = 0x0};
72
+	EN_RXADDR_REGISTER enableRxAddressesRegisterContents = {.byte = 0x0};
73
+	RX_PW_Pn_REGISTER rxPwPnRegisterContents = {.byte = 0x0};
74
+	EN_AA_REGISTER enAaRegister = {.byte = 0x0};
67 75
 	FEATURE_REGISTER featureRegisterContents = {.byte = 0x0};
68 76
 	DYNPD_REGISTER dyndpRegisterContents = {.byte = 0x0};
69
-	SETUP_RETR_REGISTER setupRetrRegisterContents = {.byte = 0x0};
70 77
 
71 78
 	uint8_t txAddress[5] = {0xB3, 0xB3, 0xB3, 0xB3, 0x00};
72
-	uint8_t rx0Address[5] = {0xB3, 0xB3, 0xB3, 0xB3, 0x20};
73
-	/* 
74
-	 * - Length of CRC (CRCO in CONFIG)
75
-	 * - Enable auto acknowledgment (EN_AA)
76
-	 *   -> Register already set correctly after reset
77
-	 * - Enable data pipes (EN_RXADDR)?
78
-	 *   -> Two pipes are already enabled on reset
79
-	 * - Set up address width (SETUP_AW)
80
-	 *   -> 3 bytes
81
-	 * - Automatic Retransmission (SETUP_RETR)
82
-	 *   -> ARD = 0b0000
83
-	 *   -> 3 retransmits -> ARC = 0b0011
84
-	 *   -> Register already set correctly after reset
85
-	 * - RF Channel (RF_CH)
86
-	 *   -> RF_CH = 0b1010000
87
-	 * - RF Setup (RF_SETUP)
88
-	 *   -> first use reset values, can be fine tuned later
89
-	 * - Enable dynamic payload length (DYNPD) -> command activate + 0x73, then set bits in FEATURE?
90
-	 */
91
-
92
-	/* Set the address width to 3 bytes */
93
-	//Write_NRF_Register(0x03, 0x1);
79
+	uint8_t rx1Address[5] = {0xB3, 0xB3, 0xB3, 0xB3, 0x00};
94 80
 
95 81
 	/* Set the frequency to 1450 MHz */
96 82
 	Write_NRF_Register(RF_CH_ADDRESS, 0x32);
@@ -100,12 +86,10 @@ void Configure_Transmission(uint8_t moduleId)
100 86
 	featureRegisterContents.bits.EN_DPL = 1; // enable dynamic payload length
101 87
 	Write_NRF_Register(FEATURE_ADDRESS, featureRegisterContents.byte);
102 88
 
103
-	/* */
104
-	setupRetrRegisterContents.bits.ARC = 0x3;
105
-	setupRetrRegisterContents.bits.ARD = 0xF;
106
-	Write_NRF_Register(SETUP_RETR_ADDRESS, setupRetrRegisterContents.byte);
107
-
108
-	/* set dynamic payload length for all data pipes */ // TODO: only pipe 0 is currently in use -> don't set the other values
89
+	/* set dynamic payload length for all data pipes
90
+	 * When the dynamic payload length is not set the module cannot receive packets from some
91
+	 * stations. This is probably due to counterfeit NRF24L01+ chips.
92
+	 */
109 93
 	dyndpRegisterContents.bits.DPL_P0 = 1;
110 94
 	dyndpRegisterContents.bits.DPL_P1 = 1;
111 95
 	dyndpRegisterContents.bits.DPL_P2 = 1;
@@ -114,23 +98,62 @@ void Configure_Transmission(uint8_t moduleId)
114 98
 	dyndpRegisterContents.bits.DPL_P5 = 1;
115 99
 	Write_NRF_Register(DYNPD_ADDRESS, dyndpRegisterContents.byte);
116 100
 
101
+	/* Set up the auto retries */
102
+	setupRetrRegisterContents.bits.ARC = 0x3;
103
+	setupRetrRegisterContents.bits.ARD = 0xF;
104
+	Write_NRF_Register(SETUP_RETR_ADDRESS, setupRetrRegisterContents.byte);
105
+
117 106
 	/* Set the TX address */
118 107
 	Set_TX_Address(txAddress, MAX_ADDRESS_LENGTH);
119 108
 
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);
109
+	/* Set the address of the RX pipe 0 to the one of the base station to receive acks */
110
+	Set_RX_P0_Address(txAddress, MAX_ADDRESS_LENGTH);
111
+
112
+	/* Set the address of the RX pipe 1 to the own address to receive messages */
113
+	rx1Address[4] = moduleId; // The last byte of the address corresponds to the Id set by the pin programming
114
+	Set_RX_P1_Address(rx1Address, MAX_ADDRESS_LENGTH);
115
+
116
+	/* Enable the rx addresses for pipe 0 and pipe 1*/
117
+	enableRxAddressesRegisterContents.bits.ERX_P0 = 1;
118
+	enableRxAddressesRegisterContents.bits.ERX_P1 = 1;
119
+	Write_NRF_Register(EN_RXADDR_ADDRESS, enableRxAddressesRegisterContents.byte);
120
+
121
+	/* Set the payload witth for pipe 1 */
122
+	rxPwPnRegisterContents.bits.RX_PW_Pn = 32;
123
+	Write_NRF_Register(RX_PW_P1_ADDRESS, rxPwPnRegisterContents.byte);
124
+
125
+	rxPwPnRegisterContents.bits.RX_PW_Pn = 0;
126
+	Write_NRF_Register(RX_PW_P0_ADDRESS, rxPwPnRegisterContents.byte); // auto-ack pipe
127
+	Write_NRF_Register(RX_PW_P2_ADDRESS, rxPwPnRegisterContents.byte); // not used
128
+	Write_NRF_Register(RX_PW_P3_ADDRESS, rxPwPnRegisterContents.byte); // not used
129
+	Write_NRF_Register(RX_PW_P4_ADDRESS, rxPwPnRegisterContents.byte); // not used
130
+	Write_NRF_Register(RX_PW_P5_ADDRESS, rxPwPnRegisterContents.byte); // not used
131
+
132
+	/* Enable auto acknowledge for pipe 1 */
133
+	enAaRegister.bits.ENAA_P0 = 1;
134
+	enAaRegister.bits.ENAA_P1 = 1;
135
+	enAaRegister.bits.ENAA_P2 = 1;
136
+	enAaRegister.bits.ENAA_P3 = 1;
137
+	enAaRegister.bits.ENAA_P4 = 1;
138
+	enAaRegister.bits.ENAA_P5 = 1;
139
+	Write_NRF_Register(EN_AA_ADDRESS, enAaRegister.byte);
140
+
141
+	/* Flush FIFOs */
142
+	Send_TX_Flush_Command();
143
+	Send_RX_Flush_Command();
122 144
 
123 145
 
124 146
 	PCMSK2 |= (1<<PCINT21); // Set the external interrupt for PD5
125 147
 }
126 148
 
127
-void NRF24L01_Send_Message(uint8_t *buffer, uint8_t length)
149
+bool NRF24L01_Send_Message(uint8_t *buffer, uint8_t length)
128 150
 {
151
+	bool success = false;
129 152
 	STATUS_REGISTER statusRegisterContents = {.byte = 0x0};
130 153
 	
131 154
 	if ((length > 32) || (length == 0))
132 155
 	{
133
-		return;
156
+		return success;
134 157
 	}
135 158
 
136 159
 	PCICR |= (1<<PCIE2); // Enable the interrupt for the IRQ signal
@@ -147,7 +170,6 @@ void NRF24L01_Send_Message(uint8_t *buffer, uint8_t length)
147 170
 	 * induced by the SPI:
148 171
 	 * https://forum.mysensors.org/topic/10452/nrf24l01-communication-failure-root-cause-and-solution
149 172
 	 */
150
-	LED_PORT |= (1 << LED_PIN);
151 173
 
152 174
 	statusRegisterContents.byte = Read_NRF_Status_Register();
153 175
 
@@ -156,6 +178,10 @@ void NRF24L01_Send_Message(uint8_t *buffer, uint8_t length)
156 178
 	{
157 179
 		Send_TX_Flush_Command(); /* Remove the packet from the TX FIFO as it is not done automatically */
158 180
 	}
181
+	else
182
+	{
183
+		success = true;
184
+	}
159 185
 	
160 186
 
161 187
 	/* Reset the interrupts */
@@ -168,57 +194,88 @@ void NRF24L01_Send_Message(uint8_t *buffer, uint8_t length)
168 194
 	nrfInterruptRaised = false;
169 195
 
170 196
 
171
-	return;
197
+	return success;
172 198
 }
173 199
 
174
-uint8_t Read_NRF_Status_Register(void)
200
+bool NRF24L01_Receive_Message(uint8_t *buffer, uint8_t duration)
175 201
 {
176
-	uint8_t registerContents;
202
+	uint8_t messageReceived = false;
203
+	CONFIG_REGISTER configRegisterContents = {.byte = 0x0};
204
+	STATUS_REGISTER statusRegisterContents = {.byte = 0x0};
205
+	FIFO_STATUS_REGISTER fifoStatusRegisterContents = {.byte = 0x0};
177 206
 
178
-	SPI_Start_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN);
179
-	registerContents = SPI_Transfer_Byte(0x00);
180
-	SPI_Stop_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN);
181
-	return registerContents;
182
-}
207
+	PCICR |= (1<<PCIE2); // Enable the interrupt for the IRQ signal
183 208
 
209
+	// Enable the receive mode
210
+	configRegisterContents.byte = Read_NRF_Register(CONFIG_ADDRESS);
211
+	configRegisterContents.bits.PRIM_RX = 0x1;
212
+	Write_NRF_Register(CONFIG_ADDRESS, configRegisterContents.byte);
184 213
 
185
-/* TODO: rewrite the read register function if it is needed (remove the read operations for the 5-byte registers)*/
186
-#if 0
187
-uint8_t Read_NRF_Register(uint8_t address, uint8_t * registerContents)
188
-{
189
-	/* TODO: simplify this function, as the registers with more than one byte are accessed with other functions */
190
-	uint8_t numberOfBytes = 0;
191 214
 
192
-	if ((address == 0x0A) ||
193
-	    (address == 0x0B) ||
194
-	    (address == 0x10))
215
+	NRF_CE_PORT |= (1 << NRF_CE_PIN);
216
+
217
+	_delay_ms(10);
218
+	while ((nrfInterruptRaised == false) && (duration > 0))
195 219
 	{
196
-		numberOfBytes = 5;
197
-	}
198
-	else
220
+		_delay_ms(1);
221
+		duration --;
222
+	};
223
+
224
+	if (nrfInterruptRaised == true) // check if a message was received
199 225
 	{
200
-		numberOfBytes = 1;
226
+		/* A message was received */
227
+
228
+		statusRegisterContents.byte = Read_NRF_Status_Register();
229
+
230
+		fifoStatusRegisterContents.byte = Read_NRF_Register(FIFO_STATUS_ADDRESS);
231
+		if (fifoStatusRegisterContents.bits.RX_EMPTY != 1)
232
+		{
233
+			messageReceived = true;
234
+		}
235
+
236
+		nrfInterruptRaised = false;
201 237
 	}
202 238
 
203
-	/* First write the address */
204
-	SPI_Start_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN);
239
+	// Set the NRF to standby
240
+	NRF_CE_PORT &= ~(1 << NRF_CE_PIN);
205 241
 
242
+	configRegisterContents.byte = Read_NRF_Register(CONFIG_ADDRESS);
243
+	configRegisterContents.bits.PRIM_RX = 0x0;
244
+	Write_NRF_Register(CONFIG_ADDRESS, configRegisterContents.byte);
206 245
 
207
-	SPI_Transfer_Byte(address);
246
+	PCICR &= ~(1<<PCIE2); // Disable the interrupt for the IRQ signal
208 247
 
209
-	/* Read the register bytes */
210
-	for (uint8_t i = 0; i < numberOfBytes; i++)
248
+	if (messageReceived == true)
211 249
 	{
212
-		/* Write dummy data to shift in the register content */
213
-		registerContents[i] = SPI_Transfer_Byte(0x0);
250
+		Read_Message_From_RX_FIFO(PACKET_LENGTH, buffer); /* TODO: only possible after CE = 0? */
214 251
 	}
215 252
 
216
-	SPI_Stop_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN);
253
+	/* Reset the interrupts */
254
+	statusRegisterContents.bits.TX_DS = 1;
255
+	statusRegisterContents.bits.MAX_RT = 1;
256
+	statusRegisterContents.bits.RX_DR = 1;
257
+	Write_NRF_Register(STATUS_ADDRESS, statusRegisterContents.byte);
258
+
259
+	return messageReceived;
260
+}
261
+
262
+uint8_t Read_NRF_Status_Register(void)
263
+{
264
+	uint8_t registerContents;
217 265
 
218
-	return numberOfBytes;
266
+	registerContents = Write_One_Byte(0x0);
267
+	return registerContents;
219 268
 }
220 269
 
221
-#endif
270
+
271
+uint8_t Read_NRF_Register(uint8_t address)
272
+{
273
+	uint8_t registerContents;
274
+
275
+	registerContents = Write_Two_Bytes(address, 0x0);
276
+
277
+	return registerContents;
278
+}
222 279
 
223 280
 void Write_NRF_Register(uint8_t address, uint8_t registerContents)
224 281
 {
@@ -230,31 +287,59 @@ void Send_Activate_Command(void)
230 287
 	Write_Two_Bytes(0x50, 0x73);
231 288
 }
232 289
 
233
-static void Write_Two_Bytes(uint8_t byte1, uint8_t byte2)
290
+void Send_TX_Flush_Command(void)
291
+{
292
+	Write_One_Byte(FLUSH_TX_COMMAND);
293
+}
294
+
295
+void Send_RX_Flush_Command(void)
234 296
 {
297
+	Write_One_Byte(FLUSH_RX_COMMAND);
298
+}
299
+
300
+static uint8_t Write_One_Byte(uint8_t byte1)
301
+{
302
+	uint8_t registerContents = 0;
235 303
 	SPI_Start_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN);
236 304
 
237
-	SPI_Transfer_Byte(byte1);
238
-	SPI_Transfer_Byte(byte2);
305
+	registerContents = SPI_Transfer_Byte(byte1);
239 306
 
240 307
 	SPI_Stop_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN);
308
+	return registerContents;
241 309
 }
242 310
 
243
-void Send_TX_Flush_Command(void)
311
+static uint8_t Write_Two_Bytes(uint8_t byte1, uint8_t byte2)
244 312
 {
245
-	/* First write the write command with the address */
313
+	uint8_t registerContents = 0;
246 314
 	SPI_Start_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN);
247 315
 
248
-	SPI_Transfer_Byte(0xE1);
316
+	SPI_Transfer_Byte(byte1);
317
+	registerContents = SPI_Transfer_Byte(byte2);
249 318
 
250 319
 	SPI_Stop_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN);
320
+	return registerContents;
251 321
 }
252 322
 
253 323
 
254 324
 
255 325
 void Write_Message_To_TX_FIFO(uint8_t length, uint8_t * buffer)
256 326
 {
257
-	Write_Byte_And_Buffer(0xA0, buffer, length);
327
+	Write_Byte_And_Buffer(W_TX_PAYLOAD_COMMAND, buffer, length);
328
+}
329
+
330
+void Read_Message_From_RX_FIFO(uint8_t length, uint8_t * buffer)
331
+{
332
+	SPI_Start_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN);
333
+
334
+	SPI_Transfer_Byte(R_RX_PAYLOAD_COMMAND);
335
+
336
+	/* Write the data byte */
337
+	for (uint8_t i = 0; i < length; i ++)
338
+	{
339
+		buffer[i] = SPI_Transfer_Byte(0x0);
340
+	}
341
+
342
+	SPI_Stop_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN);
258 343
 }
259 344
 
260 345
 void Set_TX_Address(uint8_t * txAddress, uint8_t length)
@@ -267,6 +352,11 @@ void Set_RX_P0_Address(uint8_t * rxAddress, uint8_t length)
267 352
 	Write_Byte_And_Buffer(RX_ADDR_P0_ADDRESS | 0x20, rxAddress, length);
268 353
 }
269 354
 
355
+void Set_RX_P1_Address(uint8_t * rxAddress, uint8_t length)
356
+{
357
+	Write_Byte_And_Buffer(RX_ADDR_P1_ADDRESS | 0x20, rxAddress, length);
358
+}
359
+
270 360
 static void Write_Byte_And_Buffer(uint8_t byte, uint8_t * buffer, uint8_t length)
271 361
 {
272 362
 	SPI_Start_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN);
@@ -281,5 +371,3 @@ static void Write_Byte_And_Buffer(uint8_t byte, uint8_t * buffer, uint8_t length
281 371
 
282 372
 	SPI_Stop_Transmission(&NRF_CSN_PORT, NRF_CSN_PIN);
283 373
 }
284
-
285
-//TODO: only write the used bytes into the address registers & add generic write functions

+ 27
- 10
weather-sensor/firmware/nrf24l01.h Переглянути файл

@@ -1,7 +1,9 @@
1 1
 #ifndef NRF24L01_H
2 2
 #define NRF24L01_H
3 3
 
4
-#define PACKET_BUFFER_LENGTH 22
4
+#define PACKET_LENGTH 32
5
+
6
+#define PACKET_PAYLOAD_BUFFER_LENGTH 22
5 7
 
6 8
 /* AVR I/O pin definionts */
7 9
 #define NRF_CE_DDR   DDRD
@@ -22,21 +24,24 @@ void Initialize_NRF24L01(void);
22 24
 void Set_NRF24L01_Pins(void);
23 25
 void Configure_Transmission(uint8_t moduleId);
24 26
 uint8_t Read_NRF_Status_Register(void);
25
-uint8_t Read_NRF_Register(uint8_t address, uint8_t * registerContents);
27
+uint8_t Read_NRF_Register(uint8_t address);
26 28
 void Write_NRF_Register(uint8_t address, uint8_t registerContents);
27 29
 void Send_Activate_Command(void);
28
-
29
-void NRF24L01_Send_Message(uint8_t *buffer, uint8_t length);
30
+bool NRF24L01_Send_Message(uint8_t *buffer, uint8_t length);
31
+bool NRF24L01_Receive_Message(uint8_t *buffer, uint8_t duration);
30 32
 void Write_Message_To_TX_FIFO(uint8_t length, uint8_t * buffer);
33
+void Read_Message_From_RX_FIFO(uint8_t length, uint8_t * buffer);
31 34
 void Set_TX_Address(uint8_t * txAddress, uint8_t length);
32 35
 void Set_RX_P0_Address(uint8_t * rxAddress, uint8_t length);
36
+void Set_RX_P1_Address(uint8_t * rxAddress, uint8_t length);
33 37
 
34 38
 typedef enum
35 39
 {
36
-	PACKET_TYPE_SALT = 0,
37
-	PACKET_TYPE_REPORT = 1,
38
-	PACKET_TYPE_GET_VALUES = 2,
39
-	PACKET_TYPE_VALUES = 3,
40
+	PACKET_TYPE_GET_SALT = 0,
41
+	PACKET_TYPE_SALT = 1,
42
+	PACKET_TYPE_REPORT = 2,
43
+	PACKET_TYPE_GET_VALUES = 3,
44
+	PACKET_TYPE_VALUES = 4,
40 45
 } PACKET_TYPE;
41 46
 
42 47
 typedef enum
@@ -66,8 +71,20 @@ typedef struct __attribute__((packed)) PACKET
66 71
 			uint8_t valueTypeHumidity;
67 72
 			uint16_t humidity;
68 73
 			uint8_t unused[10];
69
-		} values;
70
-		uint8_t buffer[PACKET_BUFFER_LENGTH];
74
+		} reportData;
75
+
76
+		struct {
77
+			BITFIELD_PACKET_COUNT_ELEMENT packetIdentifier;
78
+			uint8_t salt[7];
79
+			uint8_t unused[14];
80
+		} saltData;
81
+
82
+		struct {
83
+			BITFIELD_PACKET_COUNT_ELEMENT packetIdentifier;
84
+			uint8_t unused[21];
85
+		} getSaltData;
86
+
87
+		uint8_t buffer[PACKET_PAYLOAD_BUFFER_LENGTH];
71 88
 	}payload;
72 89
 	uint16_t crc;
73 90
 } PACKET;

+ 6
- 0
weather-sensor/firmware/nrf24l01_definitions.h Переглянути файл

@@ -31,6 +31,12 @@
31 31
 #define DYNPD_ADDRESS 0x1C
32 32
 #define FEATURE_ADDRESS 0x1D
33 33
 
34
+/* Commands */
35
+#define FLUSH_TX_COMMAND 0xE1
36
+#define FLUSH_RX_COMMAND 0xE2
37
+#define W_TX_PAYLOAD_COMMAND 0xA0
38
+#define R_RX_PAYLOAD_COMMAND 0x61
39
+
34 40
 /* Register bits definitions */
35 41
 /* CONFIG*/
36 42
 typedef union

+ 4
- 1
weather-sensor/firmware/pin_programming.c Переглянути файл

@@ -1,5 +1,6 @@
1 1
 #include <avr/io.h>
2 2
 #include <stdint.h>
3
+#include <util/delay.h>
3 4
 
4 5
 #include "pin_programming.h"
5 6
 
@@ -30,10 +31,12 @@ void Configure_Pin_Programming_Pins(void)
30 31
 	PIN_PROG_2_DDR &= ~(1 << PIN_PROG_2_PIN);
31 32
 	PIN_PROG_3_DDR &= ~(1 << PIN_PROG_3_PIN);
32 33
 
33
-	/* Enable pull-ups */ // TODO: enable once the boards have been fixed!
34
+	/* Enable pull-ups */
34 35
 	PIN_PROG_1_PORT |= (1 << PIN_PROG_1_PIN);
35 36
 	PIN_PROG_2_PORT |= (1 << PIN_PROG_2_PIN);
36 37
 	PIN_PROG_3_PORT |= (1 << PIN_PROG_3_PIN);
38
+
39
+	_delay_us(20);
37 40
 }
38 41
 
39 42
 uint8_t Get_Own_Identifier(void)

+ 93
- 0
weather-sensor/firmware/radio.c Переглянути файл

@@ -0,0 +1,93 @@
1
+#include <string.h>
2
+#include "radio.h"
3
+#include "encryption.h"
4
+#include "crc.h"
5
+
6
+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 */
7
+
8
+bool Send_Message(PACKET * packet, uint64_t * salt);
9
+
10
+bool Send_Get_Salt_Message(PACKET * packet, uint64_t * salt) //TODO: put into own file
11
+{
12
+	memset((uint8_t*)packet, 0, PACKET_LENGTH); //Reinitialize the buffer with zeros
13
+
14
+	packet->payload.reportData.packetIdentifier.elementCount = 0;
15
+	packet->payload.reportData.packetIdentifier.packetType = PACKET_TYPE_GET_SALT;
16
+
17
+	return Send_Message(packet, salt);
18
+}
19
+
20
+bool Send_Report_Message(PACKET * packet, uint64_t * salt, struct bme280_data * sensorData)
21
+{
22
+	packet->payload.reportData.packetIdentifier.elementCount = 3;
23
+	packet->payload.reportData.packetIdentifier.packetType = PACKET_TYPE_REPORT;
24
+
25
+	/* Fill in the payload */
26
+	packet->payload.reportData.valueTypeTemperature = VALUE_TYPE_TEMPERATURE;
27
+	packet->payload.reportData.temperature = sensorData->temperature/10;
28
+	packet->payload.reportData.valueTypePressure = VALUE_TYPE_PRESSURE;
29
+	packet->payload.reportData.pressure = sensorData->pressure;
30
+	packet->payload.reportData.valueTypeHumidity = VALUE_TYPE_HUMIDITY;
31
+	packet->payload.reportData.humidity = sensorData->humidity * 100/1024;
32
+
33
+	return Send_Message(packet, salt);
34
+}
35
+
36
+bool Send_Message(PACKET * packet, uint64_t * salt)
37
+{
38
+	bool success;
39
+
40
+	uint16_t crc;
41
+	(*salt) &= ~(1ull<<63); /* Set the most significant bit to 0 to indicate a packet from the device to the base station */
42
+
43
+	packet->salt = *salt;
44
+
45
+	/* Calculate the CRC */
46
+	crc = Calculate_Crc(packet->payload.buffer, PACKET_PAYLOAD_BUFFER_LENGTH);
47
+	packet->crc = crc;
48
+
49
+	Encrypt((uint32_t*) packet->payload.buffer,
50
+	        PACKET_PAYLOAD_BUFFER_LENGTH + sizeof(crc),
51
+	        *salt,
52
+	        (uint32_t*) encryptionKey);
53
+
54
+	success = NRF24L01_Send_Message((uint8_t*)packet, PACKET_LENGTH);
55
+
56
+	/* Increment salt */
57
+	(*salt) += (1 << 8);
58
+
59
+	return success;
60
+}
61
+
62
+bool Read_Salt_Message(PACKET * packet, uint64_t * salt)
63
+{
64
+	uint16_t crcRemainder = 0xFFFF;
65
+	uint64_t baseStationSalt = 0x0;
66
+
67
+
68
+	/* TODO: check that the packet originated from the base station by checking the id */
69
+
70
+	baseStationSalt = packet->salt;
71
+	Decrypt((uint32_t*)packet->payload.buffer,
72
+	        PACKET_PAYLOAD_BUFFER_LENGTH + sizeof(packet->crc),
73
+	        baseStationSalt,
74
+	        (uint32_t*) encryptionKey);
75
+
76
+	crcRemainder = Calculate_Crc(packet->payload.buffer,
77
+	                             PACKET_PAYLOAD_BUFFER_LENGTH + sizeof(packet->crc));
78
+	if (crcRemainder != 0)
79
+	{
80
+		return false;
81
+	}
82
+
83
+	if ((packet->payload.saltData.packetIdentifier.packetType != PACKET_TYPE_SALT) ||
84
+	    (packet->payload.saltData.packetIdentifier.elementCount != 0))
85
+	{
86
+		return false;
87
+	}
88
+
89
+	memcpy((uint8_t*)salt, packet->payload.saltData.salt, 7);
90
+	*salt = (*salt) << 8;
91
+
92
+	return true;
93
+}

+ 13
- 0
weather-sensor/firmware/radio.h Переглянути файл

@@ -0,0 +1,13 @@
1
+#ifndef RADIO_H
2
+#define RADIO_H
3
+
4
+#include <stdint.h>
5
+#include <stdbool.h>
6
+#include "bme280_defs.h"
7
+#include "nrf24l01.h"
8
+
9
+bool Send_Get_Salt_Message(PACKET * packet, uint64_t * salt); //TODO: put into own file
10
+bool Read_Salt_Message(PACKET * packet, uint64_t * salt);
11
+bool Send_Report_Message(PACKET * packet, uint64_t * salt, struct bme280_data * sensorData);
12
+
13
+#endif

Завантаження…
Відмінити
Зберегти