이어서 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 |