본문 바로가기
Study/nRF51xxx(BLE)

nRF51 DK 예제 11 - radiotest (2)

by Answer Choi 2015. 3. 6.
반응형



이어서 radio test 2번째입니다.



이부분은 앞에서 설정해준 test 값에 따라 


radio를 control하는 부분입니다.




source


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
switch (test)
        {
            case RADIO_TEST_TXCC:
                if (sweep)
                {
                    radio_sweep_end();
                    sweep = false;
                }
                radio_tx_carrier(txpower_, mode_, channel_start_);
                cur_test = test;
                test     = RADIO_TEST_NOP;
                break;
 
            case RADIO_TEST_TXMC:
                if (sweep)
                {
                    radio_sweep_end();
                    sweep = false;
                }
                radio_modulated_tx_carrier(txpower_, mode_, channel_start_);
                cur_test = test;
                test     = RADIO_TEST_NOP;
                break;
 
            case RADIO_TEST_TXSWEEP:
                radio_tx_sweep_start(txpower_, mode_, channel_start_, channel_end_, delayms_);
                sweep    = true;
                cur_test = test;
                test     = RADIO_TEST_NOP;
                break;
 
            case RADIO_TEST_RXC:
                if (sweep)
                {
                    radio_sweep_end();
                    sweep = false;
                }
                radio_rx_carrier(mode_, channel_start_);
                cur_test = test;
                test     = RADIO_TEST_NOP;
                break;  
 
            case RADIO_TEST_RXSWEEP:
                radio_rx_sweep_start(mode_, channel_start_, channel_end_, delayms_);
                sweep    = true;
                cur_test = test;
                test     = RADIO_TEST_NOP;
                break;
 
            case RADIO_TEST_NOP:
                // Fall through.
            default:
                // No implementation needed.
                break;
        }
cs


Line 3~12 : carrier를 보내는 부분입니다.


만약 sweep중이라면 sweep이 true가 되어 Line 4~8로 들어오게 됩니다.


그리고 Line 6에서 sweep를 종료시키고 sweep를 false로 만듦니다.


Line 9 : carrier를 보냅니다.


1
2
3
4
5
6
7
8
9
10
11
void radio_tx_carrier(uint8_t txpower, uint8_t mode, uint8_t channel)
{
    radio_disable();
    NRF_RADIO->SHORTS     = RADIO_SHORTS_READY_START_Msk;
    NRF_RADIO->TXPOWER    = (txpower << RADIO_TXPOWER_TXPOWER_Pos);    
    NRF_RADIO->MODE       = (mode << RADIO_MODE_MODE_Pos);
    NRF_RADIO->FREQUENCY  = channel;
    NRF_RADIO->TEST       = (RADIO_TEST_CONST_CARRIER_Enabled << RADIO_TEST_CONST_CARRIER_Pos) \
                            | (RADIO_TEST_PLL_LOCK_Enabled << RADIO_TEST_PLL_LOCK_Pos);
    NRF_RADIO->TASKS_TXEN = 1;
}
cs


앞서 설정해준 값들을 넣어준 후 carrier를 보냅니다.


Line 14~23 : 변조된 carrier를 보내는 부분입니다.


역시 sweep중이라면 disable 시킵니다.


Line 20 : 변조된 carrier를 보냅니다.


1
2
3
4
5
6
7
8
9
10
11
void radio_modulated_tx_carrier(uint8_t txpower, uint8_t mode, uint8_t channel)
{
    radio_disable();
    generate_modulated_rf_packet();
    NRF_RADIO->SHORTS     = RADIO_SHORTS_END_DISABLE_Msk | RADIO_SHORTS_READY_START_Msk | \
                            RADIO_SHORTS_DISABLED_TXEN_Msk;;
    NRF_RADIO->TXPOWER    = (txpower << RADIO_TXPOWER_TXPOWER_Pos);
    NRF_RADIO->MODE       = (mode << RADIO_MODE_MODE_Pos);
    NRF_RADIO->FREQUENCY  = channel;
    NRF_RADIO->TASKS_TXEN = 1;
}
cs


4 : 변조된 rf packet을 만들어내는 부분입니다.


packet은 아래와 같은 구조로 되어있습니다.

ADDRESS의 첫비트가 0이면 preamble은 0xAA, 1이면 0x55로 설정된다고 합니다.


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
static void generate_modulated_rf_packet(void)
{
    uint8_t i;
 
    NRF_RADIO->PREFIX0 = rnd8();
    NRF_RADIO->BASE0   = rnd32();
 
    NRF_RADIO->PCNF0  = (0UL << RADIO_PCNF0_S1LEN_Pos) |
                        (0UL << RADIO_PCNF0_S0LEN_Pos) |
                        (8UL << RADIO_PCNF0_LFLEN_Pos);
 
    NRF_RADIO->PCNF1  = (RADIO_PCNF1_WHITEEN_Enabled << RADIO_PCNF1_WHITEEN_Pos) |
                        (RADIO_PCNF1_ENDIAN_Big << RADIO_PCNF1_ENDIAN_Pos) |
                        (4UL << RADIO_PCNF1_BALEN_Pos) |
                        (0UL << RADIO_PCNF1_STATLEN_Pos) |
                        (255UL << RADIO_PCNF1_MAXLEN_Pos);
    NRF_RADIO->CRCCNF = (RADIO_CRCCNF_LEN_Disabled << RADIO_CRCCNF_LEN_Pos);
    packet[0]         = 254;    // 254 byte payload.
 
    for (i = 0; i < 254; i++)
    {
        packet[i+1= rnd8();
    }
    NRF_RADIO->PACKETPTR = (uint32_t)packet;
}
cs


5 : prefix에 8bit random number를 만들어 넣습니다.


6 : base0에 32bit random number를 만들어 넣어줍니다.


8~10 : PCN0 설정(s0=s1=0bit, length=8bit)


12~16 : PCN1 설정(Whitening enable, big edian, base address length=4bytes, 


static length=0byte, max payload length=255bytes


17 : CRC disable.


18~23 : packet에 값을 넣는데 첫번째 배열엔 254를 1~254번째는 8bit random number를


24 : 위에서 만든 packet값을 packet pointer에 넣어줍니다. 이 값은 패킷을 주고받을때 주소값으로 쓰입니다.


Line 25~30 : carrier tx sweep test입니다.


1
2
3
4
5
6
7
8
9
10
void radio_tx_sweep_start(uint8_t txpower, uint8_t mode, uint8_t channel_start, uint8_t channel_end, uint8_t delayms)
{
    txpower_       = txpower;
    mode_          = mode;
    channel_start_ = channel_start;
    channel_       = channel_start;
    channel_end_   = channel_end;
    sweep_tx_      = true;
    timer0_init(delayms);
}
cs


앞서 설정한 txpower, mode, start channel, end channel, delay등 파라메터값을 전달합니다.


각각 변수들을 대입한 후 sweep을 true로 하고 timer0을 delay값과 함께 초기화 합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
static void timer0_init(uint8_t delayms)
{
    NRF_TIMER0->TASKS_STOP = 1;
 
    NRF_TIMER0->SHORTS     = (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos);
    NRF_TIMER0->MODE       = TIMER_MODE_MODE_Timer;
    NRF_TIMER0->BITMODE    = (TIMER_BITMODE_BITMODE_24Bit << TIMER_BITMODE_BITMODE_Pos);
    NRF_TIMER0->PRESCALER  = 4;  // 1us resolution
    NRF_TIMER0->INTENSET   = (TIMER_INTENSET_COMPARE0_Set << TIMER_INTENSET_COMPARE0_Pos);
 
    NRF_TIMER0->CC[0]       = (uint32_t)delayms * 1000;
    NRF_TIMER0->TASKS_START = 1;
}
cs


Timer는 24bit로 4분주해서 1us가 됩니다.(16M/₂⁴=1MHz)


거기에 CC값을 delay값*1000을 해서 앞서 설정한 delay만큼 타이머 인터럽트가 걸립니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void TIMER0_IRQHandler(void)
{
    if (sweep_tx_)
    {
        radio_tx_carrier(txpower_, mode_, channel_);
    }
    else
    {
        radio_rx_carrier(mode_, channel_);
    }
    channel_++;
    if (channel_ > channel_end_)
    {
        channel_ = channel_start_;
    }
    NRF_TIMER0->EVENTS_COMPARE[0= 0;
}
cs


인터럽트가 걸리면, tx sweep일 경우 carrier tx가, rx sweep일 경우 carrier rx가 실행되고,


channel은 계속해서 증가해 end channel을 만나면 다시 처음부터 반복하게 됩니다.


Line 43~48 : carrier rx와 rx sweep로 carrier tx, tx sweep와 비슷합니다.


Line 50~54 : test가 RADIO_TEST_NOP이거나 그밖의 다른 값을 경우, 아무런 동작을 하지 않습니다.


반응형

'Study > nRF51xxx(BLE)' 카테고리의 다른 글

nRF51 DK 예제 12 - ram retention  (0) 2015.03.12
nRF51 SDK 업데이트  (0) 2015.03.09
nRF51 DK 예제 11 - radiotest (1)  (0) 2015.03.05
nRF51 DK 예제 10 - PWM  (2) 2015.03.04
nRF51 DK 예제 9 - PPI  (0) 2015.03.04

인기글