summaryrefslogtreecommitdiffstats
path: root/rf_test/radio.c
blob: e96d217d67cb9150dc7f5ae682124fc7f55c4d30 (plain)
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include <stdlib.h>

#include <avr/io.h>
#include <util/delay.h>

#include "radio.h"
#include "serial.h"

#define SPI_SS          PB2
#define SPI_SCK         PB5
#define SPI_MISO        PB4
#define SPI_MOSI        PB3
#define SPI_DDR         DDRB
#define SPI_PORT        PORTB

static inline uint8_t read_reg(uint8_t reg)
{
	SPI_PORT &= ~(1 << SPI_SS);
	SPDR = reg & 0x7F;
	while (!(SPSR & (1 << SPIF)))
		;
	SPDR = 0;
	while (!(SPSR & (1 << SPIF)))
		;
	SPI_PORT |= (1 << SPI_SS);

	return SPDR;
}

static inline void write_reg(uint8_t reg, uint8_t val)
{
	SPI_PORT &= ~(1 << SPI_SS);
	SPDR = reg | 0x80;
	while (!(SPSR & (1 << SPIF)))
		;
	SPDR = val;
	while (!(SPSR & (1 << SPIF)))
		;
	SPI_PORT |= (1 << SPI_SS);
}

void radio_send(const char *data, uint8_t n)
{
	uint8_t i;

	// STDBY + ListenAbort
	write_reg(0x01, 0x04);
	while ((read_reg(0x27) >> 7) != 1)
		;

	SPI_PORT &= ~(1 << SPI_SS);
	SPDR = 0x00 | 0x80;
	while (!(SPSR & (1 << SPIF)))
		;
	for (i = 0; i < n; i++) {
		SPDR = data[i];
		while (!(SPSR & (1 << SPIF)))
			;
	}
	SPI_PORT |= (1 << SPI_SS);

	write_reg(0x01, 0x0C);
	while (!read_reg(0x28))
		;

	write_reg(0x01, 0x04);
	while ((read_reg(0x27) >> 7) != 1)
		;

	// todo: do a more reliable check
	_delay_ms(10);

	// ListenOn
	write_reg(0x01, (read_reg(0x01) | 0x40));
}

uint8_t radio_recv(char *buf, uint8_t n)
{
	uint8_t read_len;

	read_len = 0;

	if ((read_reg(0x28) & 0x04))
	{
		write_reg(0x01, 0x04);
		while ((read_reg(0x27) >> 7) != 1)
			;

		SPI_PORT &= ~(1 << SPI_SS);
		SPDR = 0x00 | 0x7F;
		while (!(SPSR & (1 << SPIF)))
			;
		while (read_len < n) {
			SPDR = 0;		
			while (!(SPSR & (1 << SPIF)))
				;
			buf[read_len++] = SPDR;
		}	
		SPI_PORT |= (1 << SPI_SS);
	}
	return read_len;
}

void radio_init(struct radio_cfg *cfg)
{
	SPI_DDR |= (1 << SPI_SS) | (1 << SPI_SCK) | (1 << SPI_MOSI);
	SPI_PORT |= (1 << SPI_SS);
	SPCR |= (1 << SPE) | (1 << MSTR);
	
	write_reg(0x01, 0x04);

	// carrier freq: 434MHz
	write_reg(0x07, 0x6C);
	write_reg(0x08, 0x80);
	write_reg(0x09, 0x00);

	write_reg(0x19, (0x40 | 0x02));

	// DIO mappings
	write_reg(0x25, 0x40);
	write_reg(0x26, 0x07);

	write_reg(0x28, 0x10);

	write_reg(0x29, 0xDC);

	// packet config
	if (cfg->payload_len > 0) {
		write_reg(0x37, 0x10);
		write_reg(0x38, cfg->payload_len);
	}

	// rx delay
	write_reg(0x3D, (0x10 | 0x02 | 0x00));

	// run DAGC
	write_reg(0x6F, 0x30);

	// start listening
	write_reg(0x01, (read_reg(0x01) | 0x40));
}