Simplify RSSI/BB DMA, extract to ThreadWait class.

Also saved 688 bytes of code.
This commit is contained in:
Jared Boone 2016-02-09 09:46:29 -08:00
parent 5cd423bb20
commit ae93d8ee58
5 changed files with 101 additions and 36 deletions

View File

@ -126,6 +126,7 @@ CPPSRC = main.cpp \
message_queue.cpp \ message_queue.cpp \
event.cpp \ event.cpp \
event_m4.cpp \ event_m4.cpp \
thread_wait.cpp \
gpdma.cpp \ gpdma.cpp \
baseband_dma.cpp \ baseband_dma.cpp \
baseband_sgpio.cpp \ baseband_sgpio.cpp \

View File

@ -32,6 +32,8 @@ using namespace lpc43xx;
#include "portapack_dma.hpp" #include "portapack_dma.hpp"
#include "thread_wait.hpp"
namespace baseband { namespace baseband {
namespace dma { namespace dma {
@ -99,21 +101,19 @@ constexpr size_t msg_count = transfers_per_buffer - 1;
static std::array<gpdma::channel::LLI, transfers_per_buffer> lli_loop; static std::array<gpdma::channel::LLI, transfers_per_buffer> lli_loop;
static constexpr auto& gpdma_channel_sgpio = gpdma::channels[portapack::sgpio_gpdma_channel_number]; static constexpr auto& gpdma_channel_sgpio = gpdma::channels[portapack::sgpio_gpdma_channel_number];
static Semaphore semaphore; static ThreadWait thread_wait;
static volatile const gpdma::channel::LLI* next_lli = nullptr;
static void transfer_complete() { static void transfer_complete() {
next_lli = gpdma_channel_sgpio.next_lli(); const auto next_lli_index = gpdma_channel_sgpio.next_lli() - &lli_loop[0];
chSemSignalI(&semaphore); thread_wait.wake_from_interrupt(next_lli_index);
} }
static void dma_error() { static void dma_error() {
thread_wait.wake_from_interrupt(-1);
disable(); disable();
} }
void init() { void init() {
chSemInit(&semaphore, 0);
gpdma_channel_sgpio.set_handlers(transfer_complete, dma_error); gpdma_channel_sgpio.set_handlers(transfer_complete, dma_error);
// LPC_GPDMA->SYNC |= (1 << gpdma_src_peripheral); // LPC_GPDMA->SYNC |= (1 << gpdma_src_peripheral);
@ -138,9 +138,6 @@ void configure(
void enable(const baseband::Direction direction) { void enable(const baseband::Direction direction) {
const auto gpdma_config = config(direction); const auto gpdma_config = config(direction);
gpdma_channel_sgpio.configure(lli_loop[0], gpdma_config); gpdma_channel_sgpio.configure(lli_loop[0], gpdma_config);
chSemReset(&semaphore, 0);
gpdma_channel_sgpio.enable(); gpdma_channel_sgpio.enable();
} }
@ -153,19 +150,14 @@ void disable() {
} }
baseband::buffer_t wait_for_rx_buffer() { baseband::buffer_t wait_for_rx_buffer() {
const auto status = chSemWait(&semaphore); const auto next_index = thread_wait.sleep();
if( status == RDY_OK ) {
const auto next = next_lli; if( next_index >= 0 ) {
if( next ) {
const size_t next_index = next - &lli_loop[0];
const size_t free_index = (next_index + transfers_per_buffer - 2) & transfers_mask; const size_t free_index = (next_index + transfers_per_buffer - 2) & transfers_mask;
return { reinterpret_cast<sample_t*>(lli_loop[free_index].destaddr), transfer_samples }; return { reinterpret_cast<sample_t*>(lli_loop[free_index].destaddr), transfer_samples };
} else { } else {
return { }; return { };
} }
} else {
return { };
}
} }
} /* namespace dma */ } /* namespace dma */

View File

@ -33,6 +33,8 @@ using namespace lpc43xx;
#include "portapack_dma.hpp" #include "portapack_dma.hpp"
#include "portapack_adc.hpp" #include "portapack_adc.hpp"
#include "thread_wait.hpp"
namespace rf { namespace rf {
namespace rssi { namespace rssi {
namespace dma { namespace dma {
@ -99,20 +101,19 @@ static buffers_config_t buffers_config;
static sample_t *samples { nullptr }; static sample_t *samples { nullptr };
static gpdma::channel::LLI *lli { nullptr }; static gpdma::channel::LLI *lli { nullptr };
static Semaphore semaphore; static ThreadWait thread_wait;
static volatile const gpdma::channel::LLI* next_lli = nullptr;
static void transfer_complete() { static void transfer_complete() {
next_lli = gpdma_channel.next_lli(); const auto next_lli_index = gpdma_channel.next_lli() - &lli[0];
chSemSignalI(&semaphore); thread_wait.wake_from_interrupt(next_lli_index);
} }
static void dma_error() { static void dma_error() {
thread_wait.wake_from_interrupt(-1);
disable(); disable();
} }
void init() { void init() {
chSemInit(&semaphore, 0);
gpdma_channel.set_handlers(transfer_complete, dma_error); gpdma_channel.set_handlers(transfer_complete, dma_error);
// LPC_GPDMA->SYNC |= (1 << gpdma_peripheral); // LPC_GPDMA->SYNC |= (1 << gpdma_peripheral);
@ -147,8 +148,6 @@ void free() {
void enable() { void enable() {
const auto gpdma_config = config(); const auto gpdma_config = config();
gpdma_channel.configure(lli[0], gpdma_config); gpdma_channel.configure(lli[0], gpdma_config);
chSemReset(&semaphore, 0);
gpdma_channel.enable(); gpdma_channel.enable();
} }
@ -161,16 +160,11 @@ void disable() {
} }
rf::rssi::buffer_t wait_for_buffer() { rf::rssi::buffer_t wait_for_buffer() {
const auto status = chSemWait(&semaphore); const auto next_index = thread_wait.sleep();
if( status == RDY_OK ) {
const auto next = next_lli; if( next_index >= 0 ) {
if( next ) {
const size_t next_index = next - &lli[0];
const size_t free_index = (next_index + buffers_config.count - 2) % buffers_config.count; const size_t free_index = (next_index + buffers_config.count - 2) % buffers_config.count;
return { reinterpret_cast<sample_t*>(lli[free_index].destaddr), buffers_config.items_per_buffer }; return { reinterpret_cast<sample_t*>(lli[free_index].destaddr), buffers_config.items_per_buffer };
} else {
return { nullptr, 0 };
}
} else { } else {
// TODO: Should I return here, or loop if RDY_RESET? // TODO: Should I return here, or loop if RDY_RESET?
return { nullptr, 0 }; return { nullptr, 0 };

View File

@ -0,0 +1,42 @@
/*
* Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc.
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "thread_wait.hpp"
int ThreadWait::sleep() {
chSysLock();
thread_to_wake = chThdSelf();
chSchGoSleepS(THD_STATE_SUSPENDED);
const auto result = chThdSelf()->p_u.rdymsg;
chSysUnlock();
return result;
}
bool ThreadWait::wake_from_interrupt(const int value) {
if( thread_to_wake ) {
thread_to_wake->p_u.rdymsg = value;
chSchReadyI(thread_to_wake);
thread_to_wake = nullptr;
return true;
} else {
return false;
}
}

View File

@ -0,0 +1,36 @@
/*
* Copyright (C) 2016 Jared Boone, ShareBrained Technology, Inc.
*
* This file is part of PortaPack.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef __THREAD_WAIT_H__
#define __THREAD_WAIT_H__
#include <ch.h>
class ThreadWait {
public:
int sleep();
bool wake_from_interrupt(const int value);
private:
Thread* thread_to_wake { nullptr };
};
#endif/*__THREAD_WAIT_H__*/