#include #if CONFIG_HAL_BOARD == HAL_BOARD_LINUX #include #include #include #include #include #include #include #include #include #include #include #include #include "RCInput.h" using namespace Linux; LinuxRCInput::LinuxRCInput() : new_rc_input(false), _channel_counter(-1) {} void LinuxRCInput::init(void* machtnichts) { int mem_fd = open("/dev/mem", O_RDWR|O_SYNC); ring_buffer = (volatile struct ring_buffer*) mmap(0, 0x1000, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd, RCIN_PRUSS_SHAREDRAM_BASE); close(mem_fd); ring_buffer->ring_head = 0; } bool LinuxRCInput::new_input() { return new_rc_input; } uint8_t LinuxRCInput::num_channels() { return _num_channels; } uint16_t LinuxRCInput::read(uint8_t ch) { new_rc_input = false; if (_override[ch]) { return _override[ch]; } return _pulse_capt[ch]; } uint8_t LinuxRCInput::read(uint16_t* periods, uint8_t len) { uint8_t i; for (i=0; i LINUX_RC_INPUT_NUM_CHANNELS){ len = LINUX_RC_INPUT_NUM_CHANNELS; } for (uint8_t i = 0; i < len; i++) { res |= set_override(i, overrides[i]); } return res; } bool LinuxRCInput::set_override(uint8_t channel, int16_t override) { if (override < 0) return false; /* -1: no change. */ if (channel < LINUX_RC_INPUT_NUM_CHANNELS) { _override[channel] = override; if (override != 0) { new_rc_input = true; return true; } } return false; } void LinuxRCInput::clear_overrides() { for (uint8_t i = 0; i < LINUX_RC_INPUT_NUM_CHANNELS; i++) { _override[i] = 0; } } /* process a pulse of the given width */ void LinuxRCInput::_process_pulse(uint16_t width_usec) { if (width_usec >= 4000) { // a long pulse indicates the end of a frame. Reset the // channel counter so next pulse is channel 0 if (_channel_counter != -1) { new_rc_input = true; _num_channels = _channel_counter; } _channel_counter = 0; return; } if (_channel_counter == -1) { // we are not synchronised return; } // take a reading for the current channel _pulse_capt[_channel_counter] = width_usec; // move to next channel _channel_counter++; // if we have reached the maximum supported channels then // mark as unsynchronised, so we wait for a wide pulse if (_channel_counter >= LINUX_RC_INPUT_NUM_CHANNELS) { new_rc_input = true; _channel_counter = -1; _num_channels = _channel_counter; } } /* called at 1kHz to check for new pulse capture data from the PRU */ void LinuxRCInput::_timer_tick() { while (ring_buffer->ring_head != ring_buffer->ring_tail) { if (ring_buffer->ring_tail >= NUM_RING_ENTRIES) { // invalid ring_tail from PRU - ignore RC input return; } if (ring_buffer->buffer[ring_buffer->ring_head].pin_value == 1) { // remember the time we spent in the low state _s0_time = ring_buffer->buffer[ring_buffer->ring_head].delta_t; } else { // the pulse value is the sum of the time spent in the low // and high states _process_pulse(ring_buffer->buffer[ring_buffer->ring_head].delta_t + _s0_time); } // move to the next ring buffer entry ring_buffer->ring_head = (ring_buffer->ring_head + 1) % NUM_RING_ENTRIES; } } #endif // CONFIG_HAL_BOARD