diff options
Diffstat (limited to 'src/fig/FIGCarousel.cpp')
-rw-r--r-- | src/fig/FIGCarousel.cpp | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/src/fig/FIGCarousel.cpp b/src/fig/FIGCarousel.cpp new file mode 100644 index 0000000..021dd80 --- /dev/null +++ b/src/fig/FIGCarousel.cpp @@ -0,0 +1,199 @@ +/* + Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, + 2011, 2012 Her Majesty the Queen in Right of Canada (Communications + Research Center Canada) + + Copyright (C) 2015 + Matthias P. Braendli, matthias.braendli@mpb.li + + Implementation of the FIG carousel to schedule the FIGs into the + FIBs. + */ +/* + This file is part of ODR-DabMux. + + ODR-DabMux 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 3 of the + License, or (at your option) any later version. + + ODR-DabMux 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 ODR-DabMux. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "fig/FIGCarousel.h" +#include <boost/format.hpp> +#include <iostream> +#include <deque> + +/**************** FIGCarouselElement ****************/ +void FIGCarouselElement::reduce_deadline() +{ + deadline -= 24; //ms + + std::cerr << "FIG " << fig->name() << + " deadline decreased to: " << deadline << std::endl; + + if (deadline < 0) { + std::cerr << "FIG " << fig->name() << + " has negative scheduling deadline" << std::endl; + } +} + +void FIGCarouselElement::increase_deadline() +{ + deadline += rate_increment_ms(fig->repetition_rate()); + + std::cerr << "FIG " << fig->name() << + " deadline increased to: " << deadline << std::endl; +} + + +/**************** FIGCarousel *****************/ + +FIGCarousel::FIGCarousel(boost::shared_ptr<dabEnsemble> ensemble) : + m_rti(ensemble), + m_fig0_0(&m_rti), + m_fig0_1(&m_rti), + m_fig0_2(&m_rti), + m_fig0_3(&m_rti), + m_fig0_17(&m_rti) +{ + m_figs_available[std::make_pair(0, 0)] = &m_fig0_0; + m_figs_available[std::make_pair(0, 1)] = &m_fig0_1; + m_figs_available[std::make_pair(0, 2)] = &m_fig0_2; + m_figs_available[std::make_pair(0, 3)] = &m_fig0_3; + m_figs_available[std::make_pair(0, 17)] = &m_fig0_17; + + const int fib0 = 0; + allocate_fig_to_fib(0, 0, fib0); + allocate_fig_to_fib(0, 1, fib0); + allocate_fig_to_fib(0, 2, fib0); + allocate_fig_to_fib(0, 3, fib0); + allocate_fig_to_fib(0, 17, fib0); +} + +void FIGCarousel::set_currentFrame(unsigned long currentFrame) +{ + m_rti.currentFrame = currentFrame; +} + +void FIGCarousel::allocate_fig_to_fib(int figtype, int extension, int fib) +{ + if (fib < 0 or fib >= 3) { + throw std::out_of_range("Invalid FIB"); + } + + auto fig = m_figs_available.find(std::make_pair(figtype, extension)); + + if (fig != m_figs_available.end()) { + FIGCarouselElement el; + el.fig = fig->second; + el.deadline = 0; + el.increase_deadline(); + m_fibs[fib].push_back(el); + } + else { + std::stringstream ss; + ss << "No FIG " << figtype << "/" << extension << " available"; + throw std::runtime_error(ss.str()); + } +} + +void dumpfib(uint8_t *buf, size_t bufsize) { + std::cerr << "FIB "; + for (size_t i = 0; i < bufsize; i++) { + std::cerr << boost::format("%02x ") % (unsigned int)buf[i]; + } + std::cerr << std::endl; +} + +size_t FIGCarousel::fib0(uint8_t *fib, const size_t bufsize, int framephase) { + + uint8_t *buf = fib; + + std::list<FIGCarouselElement>& figs = m_fibs[0]; + + std::cerr << "fib0(framephase=" << framephase << ")" << std::endl; + + std::deque<FIGCarouselElement*> sorted_figs; + + /* Decrement all deadlines */ + for (auto& fig_el : figs) { + fig_el.reduce_deadline(); + + sorted_figs.push_back(&fig_el); + } + + /* Sort the FIGs in the FIB according to their deadline */ + std::sort(sorted_figs.begin(), sorted_figs.end(), + []( const FIGCarouselElement* left, + const FIGCarouselElement* right) { + return left->deadline < right->deadline; + }); + + std::cerr << " Sorted figs:" << std::endl; + for (auto& fig_el : sorted_figs) { + std::cerr << " " << fig_el->fig->name() << + " d:" << fig_el->deadline << std::endl; + } + + /* Data structure to carry FIB */ + size_t available_size = bufsize; + + /* Take special care for FIG0/0 */ + auto fig0_0 = find_if(sorted_figs.begin(), sorted_figs.end(), + [](const FIGCarouselElement* f) { + std::cerr << "Check fig " << f->fig->name() << " " << + rate_increment_ms(f->fig->repetition_rate()) << std::endl; + return f->fig->repetition_rate() == FIG_rate::FIG0_0; + }); + + if (fig0_0 != sorted_figs.end()) { + sorted_figs.erase(fig0_0); + + if (framephase == 0) { // TODO check for all TM + size_t written = (*fig0_0)->fig->fill(buf, available_size); + std::cerr << "Special FIG 0/0 wrote " << + written << " bytes" << std::endl; + + if (written > 0) { + available_size -= written; + buf += written; + (*fig0_0)->increase_deadline(); + } + else { + throw std::runtime_error("Failed to write FIG0/0"); + } + } + } + + + /* Fill the FIB with the FIGs, taking the earliest deadline first */ + while (available_size > 0 and not sorted_figs.empty()) { + auto fig_el = sorted_figs[0]; + size_t written = fig_el->fig->fill(buf, available_size); + + std::cerr << " FIG " << fig_el->fig->name() << + " wrote " << written << " bytes" << std::endl; + + if (written > 0) { + available_size -= written; + buf += written; + + fig_el->increase_deadline(); + } + + sorted_figs.pop_front(); + } + + dumpfib(fib, bufsize); + + return bufsize - available_size; +} + |