blob: 408e14e9fbc5fb765ec0ef39e042899316184b33 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
#include "link.h"
#include "physical.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
typedef enum {
WAITING,
RECEIVING,
ESCAPING
} link_state;
#define FRAME_ESCAPE 0x02
#define FRAME_START 0x03
#define FRAME_END 0x10
void from_physical_layer(uint8_t byte) {
static link_state state = WAITING;
static uint16_t position = 0; //read position
static uint8_t packet_data_buffer[MAX_PACKET_SIZE];
static packet received = {packet_data_buffer, 0};
static uint8_t checksum = 0x00;
static bool previous_exists = false;
static uint8_t previous_byte;
#define start_receiving() \
position = 0; \
previous_exists = false; \
checksum = 0x00
#define accept(byte) \
if (position >= MAX_PACKET_SIZE) {start_receiving(); return;} \
if (previous_exists) { \
packet_data_buffer[position] = previous_byte; \
position = position + 1; \
checksum = checksum ^ previous_byte; \
previous_byte = byte; \
} else { \
previous_byte = byte; \
previous_exists = true; \
}
switch(state) {
case ESCAPING:
accept(byte);
state = RECEIVING;
break;
case WAITING:
if (byte == FRAME_START) {
start_receiving();
state = RECEIVING;
}
break;
case RECEIVING:
switch(byte) {
case FRAME_ESCAPE:
state = ESCAPING;
break;
case FRAME_START:
start_receiving();
break;
case FRAME_END:
state = WAITING;
uint8_t sent_checksum = previous_byte;
if (sent_checksum == checksum) {
received.length = position;
from_link_layer(&received);
}
break;
default:
accept(byte);
break;
}
}
#undef accept
#undef start_receiving
}
void to_link_layer(packet* s) {
uint8_t checksum = 0x00;
uint8_t byte;
int i;
to_physical_layer(FRAME_START);
for (i = 0; i < (s->length); ++i) {
byte = s->data[i];
if (byte == FRAME_START || byte == FRAME_END || byte == FRAME_ESCAPE)
to_physical_layer(FRAME_ESCAPE);
checksum = checksum ^ byte;
to_physical_layer(byte);
}
if (checksum == FRAME_START || checksum == FRAME_END || checksum == FRAME_ESCAPE)
to_physical_layer(FRAME_ESCAPE);
to_physical_layer(checksum);
to_physical_layer(FRAME_END);
};
|