summaryrefslogtreecommitdiff
path: root/nrf24l01.h
blob: 95d3f48e1464494b5f60e33601c1644d6132501a (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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#ifndef __NRF24L01__H
#define __NRF24L01__H

#include <unistd.h>
#include <avr/io.h>
#include <util/delay.h>
#include "spi.h"

#define PORT_NRF24L01                  PORTB
#define DDR_NRF24L01                   DDRB
#define DD_CE                          DDB1
#define DD_IRQ                         DDB0

#define NRF24L01_CMD_R_REGISTER        0x00
#define NRF24L01_CMD_W_REGISTER        0x20
#define NRF24L01_CMD_R_RX_PAYLOAD      0x61
#define NRF24L01_CMD_W_TX_PAYLOAD      0xA0
#define NRF24L01_CMD_NOP               0xFF
#define NRF24L01_CMD_FLUSH_TX          0xE1

#define NRF24L01_REG_STATUS            0x07
#define NRF24L01_REG_STATUS_RX_DR      0x06
#define NRF24L01_REG_STATUS_TX_DS      0x05
#define NRF24L01_REG_STATUS_MAX_RT     0x04
#define NRF24L01_REG_RX_PW_P0          0x11
#define NRF24L01_REG_EN_AA             0x01
#define NRF24L01_REG_SETUP_RETR        0x04
#define NRF24L01_REG_CONFIG            0x00
#define NRF24L01_REG_CONFIG_EN_CRC     0x3
#define NRF24L01_REG_CONFIG_PWR_UP     0x1
#define NRF24L01_REG_CONFIG_PRIM_RX    0x0

#define MAX_PAYLOAD_IN_BYTES           1

static inline void nrf24l01_ce_high()
{
  PORT_NRF24L01 |= _BV(DD_CE);
}

static inline void nrf24l01_ce_low()
{
  PORT_NRF24L01 &= ~_BV(DD_CE);
}

static inline uint8_t nrf24l01_read_cmd(uint8_t cmd)
{
  return spi_two_byte(cmd, NRF24L01_CMD_NOP);
}

static inline uint8_t nrf24l01_read_reg(uint8_t reg)
{
  return nrf24l01_read_cmd(NRF24L01_CMD_R_REGISTER | reg);
}

static inline void nrf24l01_write_cmd(uint8_t cmd, uint8_t data)
{
  spi_two_byte(cmd, data);
}

static inline void nrf24l01_write_reg(uint8_t reg, uint8_t data)
{
  nrf24l01_write_cmd(NRF24L01_CMD_W_REGISTER | reg, data);
}

static inline void nrf24l01_power_up()
{
  uint8_t config = nrf24l01_read_reg(NRF24L01_REG_CONFIG);
  nrf24l01_write_reg(NRF24L01_REG_CONFIG, config | _BV(NRF24L01_REG_CONFIG_PWR_UP));
  _delay_us(10);
}

static inline void nrf24l01_power_down()
{
  uint8_t config = nrf24l01_read_reg(NRF24L01_REG_CONFIG);
  nrf24l01_write_reg(NRF24L01_REG_CONFIG, config & ~_BV(NRF24L01_REG_CONFIG_PWR_UP));
}

static inline void nrf24l01_init()
{
  spi_init();

  //nrf24l01_write_reg(NRF24L01_REG_SETUP_RETR, 0x00);
  //nrf24l01_write_reg(NRF24L01_REG_EN_AA, 0x00);
  nrf24l01_write_reg(NRF24L01_REG_RX_PW_P0, MAX_PAYLOAD_IN_BYTES);
  nrf24l01_ce_low();
}

static inline void nrf24l01_receive_mode()
{
  uint8_t config = nrf24l01_read_reg(NRF24L01_REG_CONFIG);
  nrf24l01_write_reg(NRF24L01_REG_CONFIG, config | _BV(NRF24L01_REG_CONFIG_PRIM_RX));
  nrf24l01_ce_high();
  _delay_us(200);
}

static inline void nrf24l01_transmit_mode()
{
  uint8_t config = nrf24l01_read_reg(NRF24L01_REG_CONFIG);
  config &= ~_BV(NRF24L01_REG_CONFIG_PRIM_RX);

  nrf24l01_ce_low();
  nrf24l01_write_reg(NRF24L01_REG_CONFIG, config);
  nrf24l01_ce_high();
  _delay_us(15);
  nrf24l01_ce_low();
  _delay_us(200);
}

static inline uint8_t is_data_received()
{
  uint8_t status = nrf24l01_read_reg(NRF24L01_REG_STATUS);
  return status  & _BV(NRF24L01_REG_STATUS_RX_DR);
}

static inline uint8_t nrf24l01_receive_byte()
{
  return nrf24l01_read_cmd(NRF24L01_CMD_R_RX_PAYLOAD);
}

static inline uint8_t is_data_transmitted(uint8_t status)
{
  return status & _BV(NRF24L01_REG_STATUS_TX_DS);
}

static inline uint8_t is_data_transmit_failed(uint8_t status)
{
  return status & _BV(NRF24L01_REG_STATUS_MAX_RT);
}

static inline int nrf24l01_send_byte(uint8_t data)
{
  nrf24l01_write_cmd(NRF24L01_CMD_W_TX_PAYLOAD, data);
  nrf24l01_transmit_mode();

  uint8_t status;
  uint8_t err = 0;

  while (1) {
    status = nrf24l01_read_reg(NRF24L01_REG_STATUS);

    if(is_data_transmitted(status)) {
      nrf24l01_write_reg(NRF24L01_REG_STATUS, status);
      break;
    }

    if(is_data_transmit_failed(status)) {
      nrf24l01_write_cmd(NRF24L01_CMD_FLUSH_TX, NRF24L01_CMD_NOP);
      err = 1;
      break;
    }

    _delay_us(10000);
  }

  nrf24l01_write_reg(NRF24L01_REG_STATUS, status);
  nrf24l01_receive_mode();
  return err;
}

#endif // NRF24L01__H