mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-09-10 16:49:36 +00:00
Initial firmware commit.
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __ADC_H__
|
||||
#define __ADC_H__
|
||||
|
||||
#include "hal.h"
|
||||
|
||||
namespace lpc43xx {
|
||||
namespace adc {
|
||||
|
||||
constexpr size_t clock_rate_max = 4500000U;
|
||||
|
||||
struct CR {
|
||||
uint32_t sel;
|
||||
uint32_t clkdiv;
|
||||
uint32_t resolution;
|
||||
uint32_t edge;
|
||||
|
||||
constexpr operator uint32_t() const {
|
||||
return
|
||||
((sel & 0xff) << 0)
|
||||
| ((clkdiv & 0xff) << 8)
|
||||
| ((0 & 1) << 16)
|
||||
| (((10 - resolution) & 7) << 17)
|
||||
| ((1 & 1) << 21)
|
||||
| ((0 & 7) << 24)
|
||||
| ((edge & 1) << 27)
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
struct Config {
|
||||
uint32_t cr;
|
||||
};
|
||||
|
||||
class ADC {
|
||||
public:
|
||||
constexpr ADC(
|
||||
LPC_ADCx_Type* adcp
|
||||
) : adcp(adcp)
|
||||
{
|
||||
}
|
||||
|
||||
void power_up(const Config config) const {
|
||||
adcp->CR = config.cr;
|
||||
}
|
||||
|
||||
void clock_enable() const {
|
||||
if( adcp == LPC_ADC0 ) {
|
||||
LPC_CCU1->CLK_APB3_ADC0_CFG.AUTO = 1;
|
||||
LPC_CCU1->CLK_APB3_ADC0_CFG.RUN = 1;
|
||||
}
|
||||
if( adcp == LPC_ADC1 ) {
|
||||
LPC_CCU1->CLK_APB3_ADC1_CFG.AUTO = 1;
|
||||
LPC_CCU1->CLK_APB3_ADC1_CFG.RUN = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void clock_disable() const {
|
||||
if( adcp == LPC_ADC0 ) {
|
||||
LPC_CCU1->CLK_APB3_ADC0_CFG.RUN = 0;
|
||||
}
|
||||
if( adcp == LPC_ADC1 ) {
|
||||
LPC_CCU1->CLK_APB3_ADC1_CFG.RUN = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void disable() const {
|
||||
adcp->INTEN = 0;
|
||||
adcp->CR = 0;
|
||||
|
||||
clock_disable();
|
||||
}
|
||||
|
||||
void interrupts_disable() const {
|
||||
adcp->INTEN = 0;
|
||||
}
|
||||
|
||||
void interrupts_enable(const uint32_t mask) const {
|
||||
adcp->INTEN = mask;
|
||||
}
|
||||
|
||||
void start_burst() const {
|
||||
adcp->CR |= (1U << 16);
|
||||
}
|
||||
|
||||
void start_once() const {
|
||||
adcp->CR |= (1U << 24);
|
||||
}
|
||||
|
||||
void start_once(size_t n) const {
|
||||
uint32_t cr = adcp->CR;
|
||||
cr &= ~(0xffU);
|
||||
cr |= (1 << 24) | (1 << n);
|
||||
adcp->CR = cr;
|
||||
}
|
||||
|
||||
void stop_burst() const {
|
||||
adcp->CR &= ~(1U << 16);
|
||||
}
|
||||
|
||||
uint32_t convert(size_t n) const {
|
||||
start_once(n);
|
||||
while(true) {
|
||||
const uint32_t data = adcp->DR[n];
|
||||
if( (data >> 31) & 1 ) {
|
||||
return (data >> 6) & 0x3ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
LPC_ADCx_Type* const adcp;
|
||||
};
|
||||
|
||||
} /* namespace adc */
|
||||
} /* namespace lpc43xx */
|
||||
|
||||
#endif/*__ADC_H__*/
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 "audio.hpp"
|
||||
|
||||
namespace audio {
|
||||
|
||||
} /* namespace audio */
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __AUDIO_H__
|
||||
#define __AUDIO_H__
|
||||
|
||||
#include "buffer.hpp"
|
||||
|
||||
#include "i2s.hpp"
|
||||
using namespace lpc43xx;
|
||||
|
||||
namespace audio {
|
||||
|
||||
struct sample_t {
|
||||
union {
|
||||
struct {
|
||||
int16_t left;
|
||||
int16_t right;
|
||||
};
|
||||
uint32_t raw;
|
||||
};
|
||||
};
|
||||
|
||||
using buffer_t = buffer_t<sample_t>;
|
||||
|
||||
constexpr i2s::ConfigTX i2s0_config_tx {
|
||||
.dao = i2s::DAO {
|
||||
.wordwidth = i2s::WordWidth::Bits16,
|
||||
.mono = 0,
|
||||
.stop = 1,
|
||||
.reset = 0,
|
||||
.ws_sel = 0,
|
||||
.ws_halfperiod = 0x0f,
|
||||
.mute = 1,
|
||||
},
|
||||
.txrate = i2s::MCLKRate {
|
||||
.x_divider = 0,
|
||||
.y_divider = 0,
|
||||
},
|
||||
.txbitrate = i2s::BitRate {
|
||||
.bitrate = 7,
|
||||
},
|
||||
.txmode = i2s::Mode {
|
||||
.clksel = i2s::ClockSelect::BaseAudioClkOrExternalMCLK,
|
||||
.four_pin = 0,
|
||||
.mclk_out_en = 1,
|
||||
},
|
||||
};
|
||||
|
||||
constexpr i2s::ConfigRX i2s0_config_rx {
|
||||
.dai = i2s::DAI {
|
||||
.wordwidth = i2s::WordWidth::Bits16,
|
||||
.mono = 0,
|
||||
.stop = 1,
|
||||
.reset = 0,
|
||||
.ws_sel = 1,
|
||||
.ws_halfperiod = 0x0f,
|
||||
},
|
||||
.rxrate = i2s::MCLKRate {
|
||||
.x_divider = 0,
|
||||
.y_divider = 0,
|
||||
},
|
||||
.rxbitrate = i2s::BitRate {
|
||||
.bitrate = 7,
|
||||
},
|
||||
.rxmode = i2s::Mode {
|
||||
.clksel = i2s::ClockSelect::BaseAudioClkOrExternalMCLK,
|
||||
.four_pin = 1,
|
||||
.mclk_out_en = 0,
|
||||
},
|
||||
};
|
||||
|
||||
constexpr i2s::ConfigDMA i2s0_config_dma {
|
||||
.dma1 = i2s::DMA {
|
||||
.rx_enable = 1,
|
||||
.tx_enable = 0,
|
||||
.rx_depth = 4,
|
||||
.tx_depth = 0,
|
||||
},
|
||||
.dma2 = i2s::DMA {
|
||||
.rx_enable = 0,
|
||||
.tx_enable = 1,
|
||||
.rx_depth = 0,
|
||||
.tx_depth = 4,
|
||||
},
|
||||
};
|
||||
|
||||
} /* namespace audio */
|
||||
|
||||
#endif/*__AUDIO_H__*/
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __BASEBAND_H__
|
||||
#define __BASEBAND_H__
|
||||
|
||||
#include "complex.hpp"
|
||||
#include "buffer.hpp"
|
||||
|
||||
namespace baseband {
|
||||
|
||||
using sample_t = complex8_t;
|
||||
using buffer_t = buffer_t<sample_t>;
|
||||
|
||||
enum class Direction {
|
||||
Receive = 0,
|
||||
Transmit = 1,
|
||||
};
|
||||
|
||||
buffer_t wait_for_rx_buffer();
|
||||
|
||||
} /* namespace baseband */
|
||||
|
||||
#endif/*__BASEBAND_H__*/
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __BUFFER_H__
|
||||
#define __BUFFER_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
template<typename T>
|
||||
struct buffer_t {
|
||||
T* const p;
|
||||
const size_t count;
|
||||
const uint32_t sampling_rate;
|
||||
|
||||
constexpr buffer_t(
|
||||
T* const p,
|
||||
const size_t count
|
||||
) : p { p },
|
||||
count { count },
|
||||
sampling_rate { 0 }
|
||||
{
|
||||
};
|
||||
|
||||
constexpr buffer_t(
|
||||
T* const p,
|
||||
const size_t count,
|
||||
const uint32_t sampling_rate
|
||||
) : p { p },
|
||||
count { count },
|
||||
sampling_rate { sampling_rate }
|
||||
{
|
||||
};
|
||||
};
|
||||
|
||||
#endif/*__BUFFER_H__*/
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __COMPLEX_H__
|
||||
#define __COMPLEX_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <complex>
|
||||
#include <cmath>
|
||||
|
||||
#include <hal.h>
|
||||
|
||||
constexpr float pi { 3.141592653589793238462643383279502884f };
|
||||
|
||||
namespace std {
|
||||
|
||||
template<> struct complex<int8_t> {
|
||||
public:
|
||||
typedef int8_t value_type;
|
||||
typedef uint16_t rep_type;
|
||||
|
||||
// constexpr complex(
|
||||
// rep_type r
|
||||
// ) : _rep { r }
|
||||
// {
|
||||
// }
|
||||
|
||||
constexpr complex(
|
||||
int8_t re = 0,
|
||||
int8_t im = 0
|
||||
) : _v { re, im }
|
||||
{
|
||||
}
|
||||
|
||||
// constexpr complex(
|
||||
// const complex& o
|
||||
// ) : _rep { o._rep }
|
||||
// {
|
||||
// }
|
||||
|
||||
constexpr int8_t real() const { return _v[0]; }
|
||||
constexpr int8_t imag() const { return _v[1]; }
|
||||
|
||||
void real(int8_t v) { _v[0] = v; }
|
||||
void imag(int8_t v) { _v[1] = v; }
|
||||
|
||||
constexpr uint16_t __rep() const {
|
||||
return _rep;
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
int8_t _v[2];
|
||||
uint16_t _rep;
|
||||
};
|
||||
};
|
||||
|
||||
template<> struct complex<int16_t> {
|
||||
public:
|
||||
typedef int16_t value_type;
|
||||
typedef uint32_t rep_type;
|
||||
|
||||
// constexpr complex(
|
||||
// rep_type r
|
||||
// ) : _rep { r }
|
||||
// {
|
||||
// }
|
||||
|
||||
constexpr complex(
|
||||
int16_t re = 0,
|
||||
int16_t im = 0
|
||||
) : _v { re, im }
|
||||
{
|
||||
}
|
||||
|
||||
// constexpr complex(
|
||||
// const complex& o
|
||||
// ) : _rep { o._rep }
|
||||
// {
|
||||
// }
|
||||
|
||||
constexpr int16_t real() const { return _v[0]; }
|
||||
constexpr int16_t imag() const { return _v[1]; }
|
||||
|
||||
void real(int16_t v) { _v[0] = v; }
|
||||
void imag(int16_t v) { _v[1] = v; }
|
||||
|
||||
constexpr uint32_t __rep() const {
|
||||
return _rep;
|
||||
}
|
||||
|
||||
private:
|
||||
union {
|
||||
int16_t _v[2];
|
||||
uint32_t _rep;
|
||||
};
|
||||
};
|
||||
|
||||
} /* namespace std */
|
||||
|
||||
using complex8_t = std::complex<int8_t>;
|
||||
using complex16_t = std::complex<int16_t>;
|
||||
using complex32_t = std::complex<int32_t>;
|
||||
|
||||
static_assert(sizeof(complex8_t) == 2, "complex8_t size wrong");
|
||||
static_assert(sizeof(complex16_t) == 4, "complex16_t size wrong");
|
||||
static_assert(sizeof(complex32_t) == 8, "complex32_t size wrong");
|
||||
|
||||
#if defined(LPC43XX_M4)
|
||||
static inline complex32_t multiply_conjugate_s16_s32(const complex16_t::rep_type a, const complex16_t::rep_type b) {
|
||||
// conjugate: conj(a + bj) = a - bj
|
||||
// multiply: (a + bj) * (c + dj) = (ac - bd) + (bc + ad)j
|
||||
// conjugate-multiply: (ac + bd) + (bc - ad)j
|
||||
//return { a.real() * b.real() + a.imag() * b.imag(), a.imag() * b.real() - a.real() * b.imag() };
|
||||
const int32_t rr = __SMULBB(a, b);
|
||||
const int32_t ii = __SMULTT(a, b);
|
||||
const int32_t r = __QADD(rr, ii);
|
||||
const int32_t ir = __SMULTB(a, b);
|
||||
const int32_t ri = __SMULBT(a, b);
|
||||
const int32_t i = __QSUB(ir, ri);
|
||||
return { r, i };
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif/*__COMPLEX_H__*/
|
||||
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 "cpld_max5.hpp"
|
||||
|
||||
#include "jtag.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
|
||||
namespace cpld {
|
||||
namespace max5 {
|
||||
|
||||
/* Enter ISP:
|
||||
* Ensures that the I/O pins transition smoothly from user mode to ISP
|
||||
* mode.
|
||||
*/
|
||||
void CPLD::enter_isp() {
|
||||
/* Enter ISP */
|
||||
shift_ir(0x2cc); //(199);
|
||||
jtag.runtest_tck(18003); // 1ms
|
||||
}
|
||||
|
||||
void CPLD::exit_isp() {
|
||||
/* Exit ISP? Reset? */
|
||||
shift_ir(0x201); //166);
|
||||
jtag.runtest_tck(18003); // 1ms
|
||||
shift_ir(0x3FF);
|
||||
jtag.runtest_tck(18000); // 1ms
|
||||
}
|
||||
|
||||
/* Sector erase:
|
||||
* Involves shifting in the instruction to erase the device and applying
|
||||
* an erase pulse or pulses. The erase pulse is automatically generated
|
||||
* internally by waiting in the run, test, or idle state for the
|
||||
* specified erase pulse time of 500 ms for the CFM block and 500 ms for
|
||||
* each sector of the user flash memory (UFM) block.
|
||||
*/
|
||||
void CPLD::bulk_erase() {
|
||||
erase_sector(0x0011);
|
||||
erase_sector(0x0001);
|
||||
erase_sector(0x0000);
|
||||
}
|
||||
|
||||
bool CPLD::program(
|
||||
const std::array<uint16_t, 3328>& block_0,
|
||||
const std::array<uint16_t, 512>& block_1
|
||||
) {
|
||||
bulk_erase();
|
||||
|
||||
/* Program:
|
||||
* involves shifting in the address, data, and program instruction and
|
||||
* generating the program pulse to program the flash cells. The program
|
||||
* pulse is automatically generated internally by waiting in the run/test/
|
||||
* idle state for the specified program pulse time of 75 μs. This process
|
||||
* is repeated for each address in the CFM and UFM blocks.
|
||||
*/
|
||||
program_block(0x0000, block_0);
|
||||
program_block(0x0001, block_1);
|
||||
|
||||
const auto verify_ok = verify(block_0, block_1);
|
||||
|
||||
if( verify_ok ) {
|
||||
/* Do "something". Not sure what, but it happens after verify. */
|
||||
/* Starts with a sequence the same as Program: Block 0. */
|
||||
/* Perhaps it is a write to tell the CPLD that the bitstream
|
||||
* verified OK, and it's OK to load and execute? And despite only
|
||||
* one bit changing, a write must be a multiple of a particular
|
||||
* length (64 bits)? */
|
||||
sector_select(0x0000);
|
||||
shift_ir(0x2F4); // Program
|
||||
jtag.runtest_tck(93); // 5 us
|
||||
|
||||
/* TODO: Use data from cpld_block_0, with appropriate bit(s) changed */
|
||||
/* Perhaps this is the "ISP_DONE" bit? */
|
||||
jtag.shift_dr(16, block_0[0] & 0xfbff);
|
||||
jtag.runtest_tck(1800); // 100us
|
||||
jtag.shift_dr(16, block_0[1]);
|
||||
jtag.runtest_tck(1800); // 100us
|
||||
jtag.shift_dr(16, block_0[2]);
|
||||
jtag.runtest_tck(1800); // 100us
|
||||
jtag.shift_dr(16, block_0[3]);
|
||||
jtag.runtest_tck(1800); // 100us
|
||||
}
|
||||
|
||||
return verify_ok;
|
||||
}
|
||||
|
||||
bool CPLD::verify(
|
||||
const std::array<uint16_t, 3328>& block_0,
|
||||
const std::array<uint16_t, 512>& block_1
|
||||
) {
|
||||
/* Verify */
|
||||
const auto block_0_success = verify_block(0x0000, block_0);
|
||||
const auto block_1_success = verify_block(0x0001, block_1);
|
||||
return block_0_success && block_1_success;
|
||||
}
|
||||
|
||||
void CPLD::sector_select(const uint16_t id) {
|
||||
shift_ir(0x203); // Sector select
|
||||
jtag.runtest_tck(93); // 5us
|
||||
jtag.shift_dr(13, id); // Sector ID
|
||||
}
|
||||
|
||||
bool CPLD::idcode_ok() {
|
||||
shift_ir(Instruction::IDCODE);
|
||||
const auto idcode = jtag.shift_dr(32, 0);
|
||||
return (idcode == IDCODE);
|
||||
}
|
||||
|
||||
std::array<uint16_t, 5> CPLD::read_silicon_id() {
|
||||
sector_select(0x0089);
|
||||
shift_ir(0x205);
|
||||
jtag.runtest_tck(93); // 5us
|
||||
|
||||
std::array<uint16_t, 5> silicon_id;
|
||||
silicon_id[0] = jtag.shift_dr(16, 0xffff);
|
||||
silicon_id[1] = jtag.shift_dr(16, 0xffff);
|
||||
silicon_id[2] = jtag.shift_dr(16, 0xffff);
|
||||
silicon_id[3] = jtag.shift_dr(16, 0xffff);
|
||||
silicon_id[4] = jtag.shift_dr(16, 0xffff);
|
||||
return silicon_id;
|
||||
}
|
||||
|
||||
/* Check ID:
|
||||
* The silicon ID is checked before any Program or Verify process. The
|
||||
* time required to read this silicon ID is relatively small compared to
|
||||
* the overall programming time.
|
||||
*/
|
||||
bool CPLD::silicon_id_ok() {
|
||||
const auto silicon_id = read_silicon_id();
|
||||
|
||||
return (
|
||||
(silicon_id[0] == 0x8232) &&
|
||||
(silicon_id[1] == 0x2aa2) &&
|
||||
(silicon_id[2] == 0x4a82) &&
|
||||
(silicon_id[3] == 0x8c0c) &&
|
||||
(silicon_id[4] == 0x0000)
|
||||
);
|
||||
}
|
||||
|
||||
void CPLD::erase_sector(const uint16_t id) {
|
||||
sector_select(id);
|
||||
shift_ir(0x2F2); // Erase pulse
|
||||
jtag.runtest_tck(9000003); // 500ms
|
||||
}
|
||||
|
||||
void CPLD::program_block(
|
||||
const uint16_t id,
|
||||
const uint16_t* const data,
|
||||
const size_t count
|
||||
) {
|
||||
sector_select(id);
|
||||
shift_ir(0x2F4); // Program
|
||||
jtag.runtest_tck(93); // 5us
|
||||
|
||||
for(size_t i=0; i<count; i++) {
|
||||
jtag.shift_dr(16, data[i]);
|
||||
jtag.runtest_tck(1800);
|
||||
}
|
||||
}
|
||||
|
||||
bool CPLD::verify_block(
|
||||
const uint16_t id,
|
||||
const uint16_t* const data,
|
||||
const size_t count
|
||||
) {
|
||||
sector_select(id);
|
||||
shift_ir(0x205); // Read
|
||||
jtag.runtest_tck(93); // 5us
|
||||
|
||||
bool success = true;
|
||||
for(size_t i=0; i<count; i++) {
|
||||
const auto from_device = jtag.shift_dr(16, 0xffff);
|
||||
if( (id == 0) && (i == 0) ) {
|
||||
// Account for bit that indicates bitstream is valid.
|
||||
if( (from_device & 0xfbff) != (data[i] & 0xfbff) ) {
|
||||
success = false;
|
||||
}
|
||||
} else {
|
||||
if( from_device != data[i] ) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool CPLD::is_blank_block(const uint16_t id, const size_t count) {
|
||||
sector_select(id);
|
||||
shift_ir(0x205); // Read
|
||||
jtag.runtest_tck(93); // 5us
|
||||
|
||||
bool success = true;
|
||||
for(size_t i=0; i<count; i++) {
|
||||
const auto from_device = jtag.shift_dr(16, 0xffff);
|
||||
if( from_device != 0xffff ) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
bool CPLD::is_blank() {
|
||||
const auto block_0_blank = is_blank_block(0x0000, 3328);
|
||||
const auto block_1_blank = is_blank_block(0x0001, 512);
|
||||
return block_0_blank && block_1_blank;
|
||||
}
|
||||
|
||||
} /* namespace max5 */
|
||||
} /* namespace cpld */
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __CPLD_MAX5_H__
|
||||
#define __CPLD_MAX5_H__
|
||||
|
||||
#include "jtag.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <array>
|
||||
#include <bitset>
|
||||
|
||||
namespace cpld {
|
||||
namespace max5 {
|
||||
|
||||
class CPLD {
|
||||
public:
|
||||
constexpr CPLD(
|
||||
jtag::JTAG& jtag
|
||||
) : jtag(jtag)
|
||||
{
|
||||
}
|
||||
|
||||
void reset() {
|
||||
jtag.reset();
|
||||
}
|
||||
|
||||
void run_test_idle() {
|
||||
jtag.run_test_idle();
|
||||
}
|
||||
|
||||
bool idcode_ok();
|
||||
|
||||
void enter_isp();
|
||||
|
||||
/* Check ID:
|
||||
* The silicon ID is checked before any Program or Verify process. The
|
||||
* time required to read this silicon ID is relatively small compared to
|
||||
* the overall programming time.
|
||||
*/
|
||||
bool silicon_id_ok();
|
||||
|
||||
void exit_isp(); // I think that's what the code does...
|
||||
|
||||
void bulk_erase();
|
||||
|
||||
bool program(
|
||||
const std::array<uint16_t, 3328>& block_0,
|
||||
const std::array<uint16_t, 512>& block_1
|
||||
);
|
||||
|
||||
bool verify(
|
||||
const std::array<uint16_t, 3328>& block_0,
|
||||
const std::array<uint16_t, 512>& block_1
|
||||
);
|
||||
|
||||
bool is_blank();
|
||||
|
||||
std::pair<bool, uint8_t> boundary_scan();
|
||||
|
||||
enum class Instruction {
|
||||
BYPASS = 0b1111111111,
|
||||
EXTEST = 0b0000001111,
|
||||
SAMPLE = 0b0000000101,
|
||||
IDCODE = 0b0000000110,
|
||||
USERCODE = 0b0000000111,
|
||||
CLAMP = 0b0000001010,
|
||||
HIGHZ = 0b0000001011
|
||||
};
|
||||
|
||||
void shift_ir(const Instruction instruction) {
|
||||
shift_ir(static_cast<uint32_t>(instruction));
|
||||
}
|
||||
|
||||
template<size_t N>
|
||||
void shift_dr(std::bitset<N>& bits) {
|
||||
jtag.shift_dr(bits);
|
||||
}
|
||||
|
||||
private:
|
||||
jtag::JTAG& jtag;
|
||||
|
||||
std::array<uint16_t, 5> read_silicon_id();
|
||||
|
||||
void sector_select(const uint16_t id);
|
||||
|
||||
void erase_sector(const uint16_t id);
|
||||
|
||||
void program_block(
|
||||
const uint16_t id,
|
||||
const uint16_t* const data,
|
||||
const size_t count
|
||||
);
|
||||
|
||||
template<size_t N>
|
||||
void program_block(
|
||||
const uint16_t id,
|
||||
const std::array<uint16_t, N>& data
|
||||
) {
|
||||
program_block(id, data.data(), data.size());
|
||||
}
|
||||
|
||||
bool verify_block(
|
||||
const uint16_t id,
|
||||
const uint16_t* const data,
|
||||
const size_t count
|
||||
);
|
||||
|
||||
template<size_t N>
|
||||
bool verify_block(
|
||||
const uint16_t id,
|
||||
const std::array<uint16_t, N>& data
|
||||
) {
|
||||
return verify_block(id, data.data(), data.size());
|
||||
}
|
||||
|
||||
bool is_blank_block(const uint16_t id, const size_t count);
|
||||
|
||||
const uint32_t IDCODE = 0b00000010000010100101000011011101;
|
||||
|
||||
const size_t IR_LENGTH = 10;
|
||||
|
||||
void shift_ir(const uint32_t value) {
|
||||
jtag.shift_ir(IR_LENGTH, value);
|
||||
}
|
||||
};
|
||||
/*
|
||||
class ModeISP {
|
||||
public:
|
||||
ModeISP(
|
||||
CPLD& cpld
|
||||
) : cpld(cpld)
|
||||
{
|
||||
cpld.enter_isp();
|
||||
}
|
||||
|
||||
~ModeISP() {
|
||||
cpld.exit_isp();
|
||||
}
|
||||
|
||||
private:
|
||||
CPLD& cpld;
|
||||
};
|
||||
*/
|
||||
} /* namespace max5 */
|
||||
} /* namespace cpld */
|
||||
|
||||
#endif/*__CPLD_MAX5_H__*/
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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 "cpu_clock.hpp"
|
||||
|
||||
#include <ch.h>
|
||||
#include <hal.h>
|
||||
|
||||
#include "lpc43xx_cpp.hpp"
|
||||
using namespace lpc43xx;
|
||||
|
||||
constexpr uint32_t systick_count(const uint32_t clock_source_f) {
|
||||
return clock_source_f / CH_FREQUENCY;
|
||||
}
|
||||
|
||||
constexpr uint32_t systick_load(const uint32_t clock_source_f) {
|
||||
return systick_count(clock_source_f) - 1;
|
||||
}
|
||||
|
||||
constexpr auto systick_count_irc = systick_load(clock_source_irc_f);
|
||||
constexpr auto systick_count_pll1 = systick_load(clock_source_pll1_f);
|
||||
constexpr auto systick_count_pll1_step = systick_load(clock_source_pll1_step_f);
|
||||
|
||||
static void set_clock(LPC_CGU_BASE_CLK_Type& clk, const cgu::CLK_SEL clock_source) {
|
||||
clk.AUTOBLOCK = 1;
|
||||
clk.CLK_SEL = toUType(clock_source);
|
||||
}
|
||||
|
||||
void cpu_clock_irc() {
|
||||
/* Set M4 clock to safe default speed (~12MHz IRC) */
|
||||
set_clock(LPC_CGU->BASE_M4_CLK, cgu::CLK_SEL::IRC);
|
||||
systick_adjust_period(systick_count_irc);
|
||||
halLPCSetSystemClock(clock_source_irc_f);
|
||||
}
|
||||
|
||||
void cpu_xtal_start() {
|
||||
LPC_CGU->XTAL_OSC_CTRL.BYPASS = 0;
|
||||
LPC_CGU->XTAL_OSC_CTRL.HF = 0;
|
||||
LPC_CGU->XTAL_OSC_CTRL.ENABLE = 0;
|
||||
halPolledDelay(US2RTT(250));
|
||||
}
|
||||
|
||||
void cpu_clock_max_speed() {
|
||||
/* Incantation from LPC43xx UM10503 section 12.2.1.1, to bring the M4
|
||||
* core clock speed to the 110 - 204MHz range.
|
||||
*/
|
||||
cpu_clock_irc();
|
||||
|
||||
cpu_xtal_start();
|
||||
|
||||
/* Step into the 90-110MHz M4 clock range */
|
||||
cgu::pll1::ctrl({
|
||||
.pd = 0,
|
||||
.bypass = 0,
|
||||
.fbsel = 0,
|
||||
.direct = 0,
|
||||
.psel = 0,
|
||||
.autoblock = 1,
|
||||
.nsel = 0,
|
||||
.msel = 16,
|
||||
.clk_sel = cgu::CLK_SEL::XTAL,
|
||||
});
|
||||
while( !cgu::pll1::is_locked() );
|
||||
|
||||
/* Switch M4 clock to PLL1 running at intermediate rate */
|
||||
set_clock(LPC_CGU->BASE_M4_CLK, cgu::CLK_SEL::PLL1);
|
||||
systick_adjust_period(systick_count_pll1_step);
|
||||
halLPCSetSystemClock(clock_source_pll1_step_f);
|
||||
|
||||
/* Delay >50us at 90-110MHz clock speed */
|
||||
halPolledDelay(US2RTT(50));
|
||||
|
||||
/* Remove /2P divider from PLL1 output to achieve full speed */
|
||||
cgu::pll1::direct();
|
||||
systick_adjust_period(systick_count_pll1);
|
||||
halLPCSetSystemClock(clock_source_pll1_f);
|
||||
}
|
||||
|
||||
void cpu_start_audio_pll() {
|
||||
cgu::pll0audio::ctrl({
|
||||
.pd = 1,
|
||||
.bypass = 0,
|
||||
.directi = 0,
|
||||
.directo = 0,
|
||||
.clken = 0,
|
||||
.frm = 0,
|
||||
.autoblock = 1,
|
||||
.pllfract_req = 1,
|
||||
.sel_ext = 0,
|
||||
.mod_pd = 0,
|
||||
.clk_sel = cgu::CLK_SEL::XTAL,
|
||||
});
|
||||
|
||||
/* For 12MHz clock source, 48kHz audio rate, 256Fs MCLK:
|
||||
* Fout=12.288MHz, Fcco=417.792MHz
|
||||
* PDEC=3, NDEC=1, PLLFRACT=0x1a1cac
|
||||
*/
|
||||
cgu::pll0audio::mdiv({
|
||||
.mdec = 0x5B6A,
|
||||
});
|
||||
cgu::pll0audio::np_div({
|
||||
.pdec = 3,
|
||||
.ndec = 1,
|
||||
});
|
||||
|
||||
cgu::pll0audio::frac({
|
||||
.pllfract_ctrl = 0x1a1cac,
|
||||
});
|
||||
|
||||
cgu::pll0audio::power_up();
|
||||
while( !cgu::pll0audio::is_locked() );
|
||||
cgu::pll0audio::clock_enable();
|
||||
|
||||
set_clock(LPC_CGU->BASE_AUDIO_CLK, cgu::CLK_SEL::PLL0AUDIO);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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 __CPU_CLOCK_H__
|
||||
#define __CPU_CLOCK_H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
constexpr uint32_t clock_source_irc_f = 12000000;
|
||||
constexpr uint32_t clock_source_gp_clkin = 20000000;
|
||||
constexpr uint32_t clock_source_pll1_step_f = 100000000;
|
||||
constexpr uint32_t clock_source_pll1_f = 200000000;
|
||||
|
||||
void cpu_clock_max_speed();
|
||||
void cpu_start_audio_pll();
|
||||
|
||||
#endif/*__CPU_CLOCK_H__*/
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 "debug.hpp"
|
||||
|
||||
#include <ch.h>
|
||||
|
||||
static void runtime_error() {
|
||||
debug_indicate_error_init();
|
||||
|
||||
while(true) {
|
||||
volatile size_t n = 1000000U;
|
||||
while(n--);
|
||||
debug_indicate_error_update();
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
void __early_init(void) {
|
||||
/* Enable unaligned exception handler */
|
||||
SCB_CCR |= (1 << 3);
|
||||
|
||||
#if defined(LPC43XX_M4)
|
||||
/* Enable MemManage, BusFault, UsageFault exception handlers */
|
||||
SCB_SHCSR |= (1 << 16);
|
||||
SCB_SHCSR |= (1 << 17);
|
||||
SCB_SHCSR |= (1 << 18);
|
||||
#endif
|
||||
}
|
||||
|
||||
void port_halt(void) {
|
||||
port_disable();
|
||||
runtime_error();
|
||||
}
|
||||
|
||||
#if defined(LPC43XX_M4)
|
||||
CH_IRQ_HANDLER(MemManageVector) {
|
||||
CH_IRQ_PROLOGUE();
|
||||
chSysHalt();
|
||||
}
|
||||
|
||||
CH_IRQ_HANDLER(BusFaultVector) {
|
||||
CH_IRQ_PROLOGUE();
|
||||
chSysHalt();
|
||||
}
|
||||
|
||||
CH_IRQ_HANDLER(UsageFaultVector) {
|
||||
CH_IRQ_PROLOGUE();
|
||||
chSysHalt();
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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 __DEBUG_H__
|
||||
#define __DEBUG_H__
|
||||
|
||||
// Defined by application to indicate error in board/hardware-specific manner.
|
||||
void debug_indicate_error_init();
|
||||
void debug_indicate_error_update();
|
||||
|
||||
#endif/*__DEBUG_H__*/
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 "dsp_fft.hpp"
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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 __DSP_FFT_H__
|
||||
#define __DSP_FFT_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <complex>
|
||||
#include <cmath>
|
||||
#include <type_traits>
|
||||
#include <array>
|
||||
|
||||
#include "complex.hpp"
|
||||
#include "hal.h"
|
||||
|
||||
namespace std {
|
||||
/* https://github.com/AE9RB/fftbench/blob/master/cxlr.hpp
|
||||
* Nice trick from AE9RB (David Turnbull) to get compiler to produce simpler
|
||||
* fma (fused multiply-accumulate) instead of worrying about NaN handling
|
||||
*/
|
||||
inline complex<float>
|
||||
operator*(const complex<float>& v1, const complex<float>& v2) {
|
||||
return complex<float> {
|
||||
v1.real() * v2.real() - v1.imag() * v2.imag(),
|
||||
v1.real() * v2.imag() + v1.imag() * v2.real()
|
||||
};
|
||||
}
|
||||
} /* namespace std */
|
||||
|
||||
constexpr bool power_of_two(const size_t n) {
|
||||
return (n & (n - 1)) == 0;
|
||||
}
|
||||
|
||||
constexpr size_t log_2(const size_t n, const size_t p = 0) {
|
||||
return (n <= 1) ? p : log_2(n / 2, p + 1);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void fft_swap(const std::array<complex16_t, N>& src, std::array<T, N>& dst) {
|
||||
static_assert(power_of_two(N), "only defined for N == power of two");
|
||||
|
||||
for(size_t i=0; i<N; i++) {
|
||||
const size_t i_rev = __RBIT(i) >> (32 - log_2(N));
|
||||
const auto s = src[i];
|
||||
dst[i_rev] = {
|
||||
static_cast<typename T::value_type>(s.real()),
|
||||
static_cast<typename T::value_type>(s.imag())
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void fft_swap_in_place(std::array<T, N>& data) {
|
||||
static_assert(power_of_two(N), "only defined for N == power of two");
|
||||
|
||||
for(size_t i=0; i<N; i++) {
|
||||
const size_t i_rev = __RBIT(i) >> (32 - log_2(N));
|
||||
std::swap(data[i], data[i_rev]);
|
||||
}
|
||||
}
|
||||
|
||||
/* http://beige.ucs.indiana.edu/B673/node14.html */
|
||||
/* http://www.drdobbs.com/cpp/a-simple-and-efficient-fft-implementatio/199500857?pgno=3 */
|
||||
|
||||
template<typename T, size_t N>
|
||||
void fft_c_preswapped(std::array<T, N>& data) {
|
||||
static_assert(power_of_two(N), "only defined for N == power of two");
|
||||
|
||||
/* Provide data to this function, pre-swapped. */
|
||||
for(size_t mmax = 1; N > mmax; mmax <<= 1) {
|
||||
const float theta = -pi / mmax;
|
||||
const float wtemp = std::sin(0.5f * theta);
|
||||
const T wp {
|
||||
-2.0f * wtemp * wtemp,
|
||||
std::sin(theta)
|
||||
};
|
||||
T w { 1.0f, 0.0f };
|
||||
for(size_t m = 0; m < mmax; ++m) {
|
||||
for(size_t i = m; i < N; i += mmax * 2) {
|
||||
const size_t j = i + mmax;
|
||||
const T temp = w * data[j];
|
||||
data[j] = data[i] - temp;
|
||||
data[i] += temp;
|
||||
}
|
||||
w += w * wp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif/*__DSP_FFT_H__*/
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __DSP_TYPES_H__
|
||||
#define __DSP_TYPES_H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "complex.hpp"
|
||||
#include "buffer.hpp"
|
||||
|
||||
using buffer_c8_t = buffer_t<complex8_t>;
|
||||
using buffer_c16_t = buffer_t<complex16_t>;
|
||||
using buffer_s16_t = buffer_t<int16_t>;
|
||||
|
||||
#endif/*__DSP_TYPES_H__*/
|
||||
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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 __FIFO_H__
|
||||
#define __FIFO_H__
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
/* FIFO implementation inspired by Linux kfifo. */
|
||||
|
||||
template<typename T, size_t K>
|
||||
class FIFO {
|
||||
public:
|
||||
constexpr FIFO(
|
||||
) : _in { 0 },
|
||||
_out { 0 }
|
||||
{
|
||||
}
|
||||
|
||||
void reset() {
|
||||
_in = _out = 0;
|
||||
}
|
||||
|
||||
void reset_out() {
|
||||
_out = _in;
|
||||
}
|
||||
|
||||
size_t len() const {
|
||||
return _in - _out;
|
||||
}
|
||||
|
||||
size_t unused() const {
|
||||
return size() - (_in - _out);
|
||||
}
|
||||
|
||||
bool is_empty() const {
|
||||
return _in == _out;
|
||||
}
|
||||
|
||||
bool is_full() const {
|
||||
return len() > mask();
|
||||
}
|
||||
/*
|
||||
bool in(const T& val) {
|
||||
const bool is_not_full = !is_full();
|
||||
if( is_not_full ) {
|
||||
_data[_in & mask()] = val;
|
||||
smp_wmb();
|
||||
_in++;
|
||||
}
|
||||
return is_not_full;
|
||||
}
|
||||
*/
|
||||
size_t in(const T* const buf, size_t len) {
|
||||
const size_t l = unused();
|
||||
if( len > l ) {
|
||||
len = l;
|
||||
}
|
||||
|
||||
copy_in(buf, len, _in);
|
||||
_in += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t in_r(const void* const buf, const size_t len) {
|
||||
if( (len + recsize()) > unused() ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
poke_n(len);
|
||||
copy_in((const T*)buf, len, _in + recsize());
|
||||
_in += len + recsize();
|
||||
return len;
|
||||
}
|
||||
/*
|
||||
bool out(T& val) {
|
||||
if( is_empty() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
val = _data[_out & mask()];
|
||||
smp_wmb();
|
||||
_out += 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
size_t out(T* const buf, size_t len) {
|
||||
len = out_peek(buf, len);
|
||||
_out += len;
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t out_r(void* const buf, size_t len) {
|
||||
if( is_empty() ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t n;
|
||||
len = out_copy_r((T*)buf, len, &n);
|
||||
_out += n + recsize();
|
||||
return len;
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr size_t size() {
|
||||
return (1UL << K);
|
||||
}
|
||||
|
||||
static constexpr size_t esize() {
|
||||
return sizeof(T);
|
||||
}
|
||||
|
||||
static constexpr size_t mask() {
|
||||
return size() - 1;
|
||||
}
|
||||
|
||||
static constexpr size_t recsize() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
void smp_wmb() {
|
||||
/*__DMB();*/
|
||||
}
|
||||
|
||||
size_t peek_n() {
|
||||
size_t l = _data[_out & mask()];
|
||||
if( recsize() > 1 ) {
|
||||
l |= _data[(_out + 1) & mask()] << 8;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
void poke_n(const size_t n) {
|
||||
_data[_in & mask()] = n & 0xff;
|
||||
if( recsize() > 1 ) {
|
||||
_data[(_in + 1) & mask()] = (n >> 8) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
void copy_in(const T* const src, const size_t len, size_t off) {
|
||||
off &= mask();
|
||||
const size_t l = std::min(len, size() - off);
|
||||
|
||||
memcpy(&_data[off], &src[0], l * esize());
|
||||
memcpy(&_data[0], &src[l], (len - l) * esize());
|
||||
smp_wmb();
|
||||
}
|
||||
|
||||
void copy_out(T* const dst, const size_t len, size_t off) {
|
||||
off &= mask();
|
||||
const size_t l = std::min(len, size() - off);
|
||||
|
||||
memcpy(&dst[0], &_data[off], l * esize());
|
||||
memcpy(&dst[l], &_data[0], (len - l) * esize());
|
||||
smp_wmb();
|
||||
}
|
||||
|
||||
size_t out_copy_r(void *buf, size_t len, size_t* const n) {
|
||||
*n = peek_n();
|
||||
|
||||
if( len > *n ) {
|
||||
len = *n;
|
||||
}
|
||||
|
||||
copy_out((T*)buf, len, _out + recsize());
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t out_peek(T* const buf, size_t buf_len) {
|
||||
const size_t l = len();
|
||||
if( buf_len > l ) {
|
||||
buf_len = l;
|
||||
}
|
||||
|
||||
copy_out(buf, buf_len, _out);
|
||||
return buf_len;
|
||||
}
|
||||
|
||||
T _data[size()];
|
||||
size_t _in;
|
||||
size_t _out;
|
||||
};
|
||||
|
||||
#endif/*__FIFO_H__*/
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 "gcc.hpp"
|
||||
|
||||
#include <ch.h>
|
||||
|
||||
#if defined(TOOLCHAIN_GCC)
|
||||
|
||||
/* Note: Added to deal with static variables:
|
||||
* undefined reference to `__dso_handle'.
|
||||
* Comes up when using random C++ features, e.g. lambdas or std::function?
|
||||
*/
|
||||
void *__dso_handle;
|
||||
|
||||
/* prevents the exception handling name demangling code getting pulled in */
|
||||
namespace __gnu_cxx {
|
||||
void __verbose_terminate_handler() {
|
||||
}
|
||||
}
|
||||
|
||||
/* NOTE: Hack to address bloat when using C++ class virtual destructors.
|
||||
*/
|
||||
extern "C" __attribute__((weak)) void __cxa_pure_virtual(void) {
|
||||
chSysHalt();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Implementing abort() eliminates requirement for _getpid(), _kill(),
|
||||
* _exit().
|
||||
*/
|
||||
extern "C" void abort() {
|
||||
/* while() loop to avoid noreturn-is-returning warning. */
|
||||
while(1) { chSysHalt(); }
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __GCC_H__
|
||||
#define __GCC_H__
|
||||
|
||||
#endif/*__GCC_H__*/
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 "gpdma.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace lpc43xx {
|
||||
namespace gpdma {
|
||||
|
||||
namespace {
|
||||
|
||||
struct ChannelHandlers {
|
||||
TCHandler tc;
|
||||
ErrHandler err;
|
||||
|
||||
constexpr ChannelHandlers(
|
||||
) : tc(nullptr),
|
||||
err(nullptr)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
static std::array<ChannelHandlers, channels.size()> handlers_table { {} };
|
||||
|
||||
namespace channel {
|
||||
|
||||
void Channel::set_handlers(const TCHandler tc_handler, const ErrHandler err_handler) const {
|
||||
handlers_table[number].tc = tc_handler;
|
||||
handlers_table[number].err = err_handler;
|
||||
}
|
||||
|
||||
void Channel::configure(
|
||||
const LLI& first_lli,
|
||||
const uint32_t config
|
||||
) const {
|
||||
disable_force();
|
||||
clear_interrupts();
|
||||
|
||||
LPC_GPDMA_Channel_Type* const channel = &LPC_GPDMA->CH[number];
|
||||
channel->SRCADDR = first_lli.srcaddr;
|
||||
channel->DESTADDR = first_lli.destaddr;
|
||||
channel->LLI = first_lli.lli;
|
||||
channel->CONTROL = first_lli.control;
|
||||
channel->CONFIG = config;
|
||||
}
|
||||
|
||||
} /* namespace channel */
|
||||
|
||||
extern "C" {
|
||||
|
||||
LOCATE_IN_RAM
|
||||
CH_IRQ_HANDLER(DMA_IRQHandler) {
|
||||
CH_IRQ_PROLOGUE();
|
||||
|
||||
chSysLockFromIsr();
|
||||
|
||||
const auto tc_stat = LPC_GPDMA->INTTCSTAT;
|
||||
/* TODO: Service the higher channel numbers first, they're higher priority
|
||||
* right?!?
|
||||
*/
|
||||
for(size_t i=0; i<handlers_table.size(); i++) {
|
||||
if( (tc_stat >> i) & 1 ) {
|
||||
if( handlers_table[i].tc ) {
|
||||
handlers_table[i].tc();
|
||||
}
|
||||
}
|
||||
}
|
||||
LPC_GPDMA->INTTCCLR = tc_stat;
|
||||
|
||||
/* Test for *any* error first, before looping, since errors should be
|
||||
* exceptional and we should spend as little time on them in the common
|
||||
* case.
|
||||
*/
|
||||
const auto err_stat = LPC_GPDMA->INTERRSTAT;
|
||||
if( err_stat ) {
|
||||
for(size_t i=0; i<handlers_table.size(); i++) {
|
||||
if( (err_stat >> i) & 1 ) {
|
||||
if( handlers_table[i].err ) {
|
||||
handlers_table[i].err();
|
||||
}
|
||||
}
|
||||
}
|
||||
LPC_GPDMA->INTERRCLR = err_stat;
|
||||
}
|
||||
|
||||
chSysUnlockFromIsr();
|
||||
|
||||
CH_IRQ_EPILOGUE();
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace gpdma */
|
||||
} /* namespace lpc43xx */
|
||||
@@ -0,0 +1,363 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __GPDMA_H__
|
||||
#define __GPDMA_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <array>
|
||||
|
||||
#include "hal.h"
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace lpc43xx {
|
||||
namespace gpdma {
|
||||
|
||||
/* LPC43xx DMA appears to be the ARM PrimeCell(R) DMA Controller, or very
|
||||
* closely related.
|
||||
* More here: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0196g/Chdcdaeb.html
|
||||
*/
|
||||
|
||||
constexpr size_t buffer_words(const size_t bytes, const size_t word_size) {
|
||||
return (bytes + word_size - 1) / word_size;
|
||||
}
|
||||
|
||||
using TCHandler = void (*)(void);
|
||||
using ErrHandler = void (*)(void);
|
||||
|
||||
enum class FlowControl {
|
||||
MemoryToMemory_DMAControl = 0x0,
|
||||
MemoryToPeripheral_DMAControl = 0x1,
|
||||
PeripheralToMemory_DMAControl = 0x2,
|
||||
SourcePeripheralToDestinationPeripheral_DMAControl = 0x3,
|
||||
SourcePeripheralToDestinationPeripheral_DestinationControl = 0x4,
|
||||
MemoryToPeripheral_PeripheralControl = 0x5,
|
||||
PeripheralToMemory_PeripheralControl = 0x6,
|
||||
SourcePeripheralToDestinationPeripheral_SourceControl = 0x7,
|
||||
};
|
||||
|
||||
static const uint_fast8_t flow_control_peripheral_source_map = 0b11011100;
|
||||
|
||||
constexpr uint_fast8_t source_endpoint_type(const FlowControl flow_control) {
|
||||
return (flow_control_peripheral_source_map >> toUType(flow_control)) & 1;
|
||||
}
|
||||
|
||||
static const uint_fast8_t flow_control_peripheral_destination_map = 0b11111010;
|
||||
|
||||
constexpr uint_fast8_t destination_endpoint_type(const FlowControl flow_control) {
|
||||
return (flow_control_peripheral_destination_map >> toUType(flow_control)) & 1;
|
||||
}
|
||||
|
||||
namespace mux {
|
||||
|
||||
enum class Peripheral0 {
|
||||
SPIFI = 0,
|
||||
SCT_CTOUT_2 = 1,
|
||||
SGPIO14 = 2,
|
||||
TIMER3_MATCH_1 = 3,
|
||||
};
|
||||
|
||||
enum class Peripheral1 {
|
||||
TIMER0_MATCH_0 = 0,
|
||||
USART0_TX = 1,
|
||||
};
|
||||
|
||||
enum class Peripheral2 {
|
||||
TIMER0_MATCH_1 = 0,
|
||||
USART0_RX = 1,
|
||||
};
|
||||
|
||||
enum class Peripheral3 {
|
||||
TIMER1_MATCH_0 = 0,
|
||||
UART1_TX = 1,
|
||||
I2S1_DMAREQ_1 = 2,
|
||||
SSP1_TX = 3,
|
||||
};
|
||||
|
||||
enum class Peripheral4 {
|
||||
TIMER1_MATCH_1 = 0,
|
||||
UART1_RX = 1,
|
||||
I2S1_DMAREQ_2 = 2,
|
||||
SSP1_RX = 3,
|
||||
};
|
||||
|
||||
enum class Peripheral5 {
|
||||
TIMER2_MATCH_0 = 0,
|
||||
USART2_TX = 1,
|
||||
SSP1_TX = 2,
|
||||
SGPIO15 = 3,
|
||||
};
|
||||
|
||||
enum class Peripheral6 {
|
||||
TIMER2_MATCH_1 = 0,
|
||||
USART2_RX = 1,
|
||||
SSP1_RX = 2,
|
||||
SGPIO14 = 3,
|
||||
};
|
||||
|
||||
enum class Peripheral7 {
|
||||
TIMER3_MATCH_0 = 0,
|
||||
USART3_TX = 1,
|
||||
SCT_DMAREQ_0 = 2,
|
||||
ADCHS_WRITE = 3,
|
||||
};
|
||||
|
||||
enum class Peripheral8 {
|
||||
TIMER3_MATCH_1 = 0,
|
||||
USART3_RX = 1,
|
||||
SCT_DMAREQ_1 = 2,
|
||||
ADCHS_READ = 3,
|
||||
};
|
||||
|
||||
enum class Peripheral9 {
|
||||
SSP0_RX = 0,
|
||||
I2S0_DMAREQ_1 = 1,
|
||||
SCT_DMAREQ_1 = 2,
|
||||
};
|
||||
|
||||
enum class Peripheral10 {
|
||||
SSP0_TX = 0,
|
||||
I2S0_DMAREQ_2 = 1,
|
||||
SCT_DMAREQ_0 = 2,
|
||||
};
|
||||
|
||||
enum class Peripheral11 {
|
||||
SSP1_RX = 0,
|
||||
SGPIO14 = 1,
|
||||
USART0_TX = 2,
|
||||
};
|
||||
|
||||
enum class Peripheral12 {
|
||||
SSP1_TX = 0,
|
||||
SGPIO15 = 1,
|
||||
USART0_RX = 2,
|
||||
};
|
||||
|
||||
enum class Peripheral13 {
|
||||
ADC0 = 0,
|
||||
SSP1_RX = 2,
|
||||
USART3_RX = 3,
|
||||
};
|
||||
|
||||
enum class Peripheral14 {
|
||||
ADC1 = 0,
|
||||
SSP1_TX = 2,
|
||||
USART3_TX = 3,
|
||||
};
|
||||
|
||||
enum class Peripheral15 {
|
||||
DAC = 0,
|
||||
SCT_CTOUT_3 = 1,
|
||||
SGPIO15 = 2,
|
||||
TIMER3_MATCH_0 = 3,
|
||||
};
|
||||
|
||||
struct MUX {
|
||||
Peripheral0 peripheral_0;
|
||||
Peripheral1 peripheral_1;
|
||||
Peripheral2 peripheral_2;
|
||||
Peripheral3 peripheral_3;
|
||||
Peripheral4 peripheral_4;
|
||||
Peripheral5 peripheral_5;
|
||||
Peripheral6 peripheral_6;
|
||||
Peripheral7 peripheral_7;
|
||||
Peripheral8 peripheral_8;
|
||||
Peripheral9 peripheral_9;
|
||||
Peripheral10 peripheral_10;
|
||||
Peripheral11 peripheral_11;
|
||||
Peripheral12 peripheral_12;
|
||||
Peripheral13 peripheral_13;
|
||||
Peripheral14 peripheral_14;
|
||||
Peripheral15 peripheral_15;
|
||||
|
||||
constexpr operator uint32_t() const {
|
||||
return
|
||||
(toUType(peripheral_0 ) << 0)
|
||||
| (toUType(peripheral_1 ) << 2)
|
||||
| (toUType(peripheral_2 ) << 4)
|
||||
| (toUType(peripheral_3 ) << 6)
|
||||
| (toUType(peripheral_4 ) << 8)
|
||||
| (toUType(peripheral_5 ) << 10)
|
||||
| (toUType(peripheral_6 ) << 12)
|
||||
| (toUType(peripheral_7 ) << 14)
|
||||
| (toUType(peripheral_8 ) << 16)
|
||||
| (toUType(peripheral_9 ) << 18)
|
||||
| (toUType(peripheral_10) << 20)
|
||||
| (toUType(peripheral_11) << 22)
|
||||
| (toUType(peripheral_12) << 24)
|
||||
| (toUType(peripheral_13) << 26)
|
||||
| (toUType(peripheral_14) << 28)
|
||||
| (toUType(peripheral_15) << 30)
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace mux */
|
||||
|
||||
namespace channel {
|
||||
|
||||
struct LLI {
|
||||
uint32_t srcaddr;
|
||||
uint32_t destaddr;
|
||||
uint32_t lli;
|
||||
uint32_t control;
|
||||
};
|
||||
|
||||
struct LLIPointer {
|
||||
uint32_t lm;
|
||||
uint32_t r;
|
||||
uint32_t lli;
|
||||
|
||||
constexpr operator uint32_t() const {
|
||||
return
|
||||
((lm & 1) << 0)
|
||||
| ((r & 1) << 1)
|
||||
| (lli & 0xfffffffc)
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
struct Control {
|
||||
uint32_t transfersize;
|
||||
uint32_t sbsize;
|
||||
uint32_t dbsize;
|
||||
uint32_t swidth;
|
||||
uint32_t dwidth;
|
||||
uint32_t s;
|
||||
uint32_t d;
|
||||
uint32_t si;
|
||||
uint32_t di;
|
||||
uint32_t prot1;
|
||||
uint32_t prot2;
|
||||
uint32_t prot3;
|
||||
uint32_t i;
|
||||
|
||||
constexpr operator uint32_t() const {
|
||||
return
|
||||
((transfersize & 0xfff) << 0)
|
||||
| ((sbsize & 7) << 12)
|
||||
| ((dbsize & 7) << 15)
|
||||
| ((swidth & 7) << 18)
|
||||
| ((dwidth & 7) << 21)
|
||||
| ((s & 1) << 24)
|
||||
| ((d & 1) << 25)
|
||||
| ((si & 1) << 26)
|
||||
| ((di & 1) << 27)
|
||||
| ((prot1 & 1) << 28)
|
||||
| ((prot2 & 1) << 29)
|
||||
| ((prot3 & 1) << 30)
|
||||
| ((i & 1) << 31)
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
struct Config {
|
||||
uint32_t e;
|
||||
uint32_t srcperipheral;
|
||||
uint32_t destperipheral;
|
||||
FlowControl flowcntrl;
|
||||
uint32_t ie;
|
||||
uint32_t itc;
|
||||
uint32_t l;
|
||||
uint32_t a;
|
||||
uint32_t h;
|
||||
|
||||
constexpr operator uint32_t() const {
|
||||
return
|
||||
((e & 1) << 0)
|
||||
| ((srcperipheral & 0x1f) << 1)
|
||||
| ((destperipheral & 0x1f) << 6)
|
||||
| ((toUType(flowcntrl) & 7) << 11)
|
||||
| ((ie & 1) << 14)
|
||||
| ((itc & 1) << 15)
|
||||
| ((l & 1) << 16)
|
||||
| ((a & 1) << 17)
|
||||
| ((h & 1) << 18)
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
class Channel {
|
||||
public:
|
||||
constexpr Channel(
|
||||
const size_t number
|
||||
) : number(number)
|
||||
{
|
||||
}
|
||||
|
||||
void enable() const {
|
||||
LPC_GPDMA->CH[number].CONFIG |= (1U << 0);
|
||||
}
|
||||
|
||||
bool is_enabled() const {
|
||||
return LPC_GPDMA->CH[number].CONFIG & (1U << 0);
|
||||
}
|
||||
|
||||
void disable_force() const {
|
||||
LPC_GPDMA->CH[number].CONFIG &= ~(1U << 0);
|
||||
}
|
||||
|
||||
void clear_interrupts() const {
|
||||
LPC_GPDMA->INTTCCLR = (1U << number);
|
||||
LPC_GPDMA->INTERRCLR = (1U << number);
|
||||
}
|
||||
|
||||
void set_handlers(const TCHandler tc_handler, const ErrHandler err_handler) const;
|
||||
|
||||
void configure(const LLI& first_lli, const uint32_t config) const;
|
||||
|
||||
const LLI* next_lli() const {
|
||||
return reinterpret_cast<LLI*>(LPC_GPDMA->CH[number].LLI);
|
||||
}
|
||||
|
||||
private:
|
||||
const size_t number;
|
||||
};
|
||||
|
||||
} /* namespace channel */
|
||||
|
||||
constexpr std::array<channel::Channel, 8> channels { {
|
||||
{ 0 }, { 1 }, { 2 }, { 3 },
|
||||
{ 4 }, { 5 }, { 6 }, { 7 },
|
||||
} };
|
||||
|
||||
class Controller {
|
||||
public:
|
||||
void enable() const {
|
||||
LPC_GPDMA->CONFIG |= (1U << 0);
|
||||
}
|
||||
|
||||
void disable() const {
|
||||
for(const auto& channel : channels) {
|
||||
channel.disable_force();
|
||||
}
|
||||
LPC_GPDMA->CONFIG &= ~(1U << 0);
|
||||
}
|
||||
};
|
||||
|
||||
constexpr Controller controller;
|
||||
|
||||
} /* namespace gpdma */
|
||||
} /* namespace lpc43xx */
|
||||
|
||||
#endif/*__GPDMA_H__*/
|
||||
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __GPIO_H__
|
||||
#define __GPIO_H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
struct PinConfig {
|
||||
const uint32_t mode : 3;
|
||||
const uint32_t pd : 1;
|
||||
const uint32_t pu : 1;
|
||||
const uint32_t fast : 1;
|
||||
const uint32_t input : 1;
|
||||
const uint32_t ifilt : 1;
|
||||
|
||||
constexpr operator uint16_t() {
|
||||
return
|
||||
((~ifilt) << 7)
|
||||
| (input << 6)
|
||||
| (fast << 5)
|
||||
| ((~pu) << 4)
|
||||
| (pd << 3)
|
||||
| (mode << 0);
|
||||
}
|
||||
/*
|
||||
constexpr operator uint32_t() {
|
||||
return scu::sfs::mode::value(mode)
|
||||
<< scu::sfs::epd::value(pd)
|
||||
<< scu::sfs::epun::value(~pu)
|
||||
<< scu::sfs::ehs::value(fast)
|
||||
<< scu::sfs::ezi::value(input)
|
||||
<< scu::sfs::zif::value(~ifilt)
|
||||
;
|
||||
}
|
||||
*/
|
||||
static constexpr PinConfig reset() {
|
||||
return { .mode = 0, .pd = 0, .pu = 1, .fast = 0, .input = 0, .ifilt = 1 };
|
||||
}
|
||||
|
||||
static constexpr PinConfig floating(
|
||||
const uint32_t mode
|
||||
) {
|
||||
return {
|
||||
.mode = mode,
|
||||
.pd = 0,
|
||||
.pu = 0,
|
||||
.fast = 0,
|
||||
.input = 0,
|
||||
.ifilt = 1
|
||||
};
|
||||
}
|
||||
|
||||
static constexpr PinConfig floating_input(
|
||||
const uint32_t mode
|
||||
) {
|
||||
return {
|
||||
.mode = mode,
|
||||
.pd = 0,
|
||||
.pu = 0,
|
||||
.fast = 0,
|
||||
.input = 1,
|
||||
.ifilt = 1
|
||||
};
|
||||
}
|
||||
|
||||
static constexpr PinConfig floating_input_with_pull(
|
||||
const uint32_t pull_direction,
|
||||
const uint32_t mode
|
||||
) {
|
||||
return {
|
||||
.mode = mode,
|
||||
.pd = (pull_direction == 0) ? 1U : 0U,
|
||||
.pu = (pull_direction == 1) ? 1U : 0U,
|
||||
.fast = 0,
|
||||
.input = 1,
|
||||
.ifilt = 1
|
||||
};
|
||||
}
|
||||
|
||||
static constexpr PinConfig gpio_led(const uint32_t mode) {
|
||||
return { .mode = mode, .pd = 0, .pu = 0, .fast = 0, .input = 0, .ifilt = 1 };
|
||||
}
|
||||
|
||||
static constexpr PinConfig gpio_inout_with_pull(
|
||||
const uint32_t mode,
|
||||
const uint32_t pull_direction
|
||||
) {
|
||||
return {
|
||||
.mode = mode,
|
||||
.pd = (pull_direction == 0) ? 1U : 0U,
|
||||
.pu = (pull_direction == 1) ? 1U : 0U,
|
||||
.fast = 0,
|
||||
.input = 1,
|
||||
.ifilt = 1
|
||||
};
|
||||
}
|
||||
|
||||
static constexpr PinConfig gpio_inout_with_pullup(const uint32_t mode) {
|
||||
return gpio_inout_with_pull(mode, 1);
|
||||
}
|
||||
|
||||
static constexpr PinConfig gpio_inout_with_pulldown(const uint32_t mode) {
|
||||
return gpio_inout_with_pull(mode, 0);
|
||||
}
|
||||
|
||||
static constexpr PinConfig gpio_out_with_pull(
|
||||
const uint32_t mode,
|
||||
const uint32_t pull_direction
|
||||
) {
|
||||
return {
|
||||
.mode = mode,
|
||||
.pd = (pull_direction == 0) ? 1U : 0U,
|
||||
.pu = (pull_direction == 1) ? 1U : 0U,
|
||||
.fast = 0,
|
||||
.input = 0,
|
||||
.ifilt = 1
|
||||
};
|
||||
}
|
||||
|
||||
static constexpr PinConfig gpio_out_with_pulldown(const uint32_t mode) {
|
||||
return gpio_out_with_pull(mode, 0);
|
||||
}
|
||||
|
||||
static constexpr PinConfig gpio_out_with_pullup(const uint32_t mode) {
|
||||
return gpio_out_with_pull(mode, 1);
|
||||
}
|
||||
|
||||
static constexpr PinConfig sgpio_in_fast(const uint32_t mode) {
|
||||
return { .mode = mode, .pd = 0, .pu = 0, .fast = 0, .input = 1, .ifilt = 0 };
|
||||
}
|
||||
|
||||
static constexpr PinConfig sgpio_out_fast_with_pull(
|
||||
const uint32_t mode,
|
||||
const uint32_t pull_direction
|
||||
) {
|
||||
return {
|
||||
.mode = mode,
|
||||
.pd = (pull_direction == 0) ? 1U : 0U,
|
||||
.pu = (pull_direction == 1) ? 1U : 0U,
|
||||
.fast = 1,
|
||||
.input = 0,
|
||||
.ifilt = 1
|
||||
};
|
||||
}
|
||||
|
||||
static constexpr PinConfig sgpio_out_fast_with_pullup(const uint32_t mode) {
|
||||
return sgpio_out_fast_with_pull(mode, 1);
|
||||
}
|
||||
|
||||
static constexpr PinConfig sgpio_inout_fast(const uint32_t mode) {
|
||||
return { .mode = mode, .pd = 0, .pu = 0, .fast = 1, .input = 1, .ifilt = 0 };
|
||||
}
|
||||
|
||||
static constexpr PinConfig i2c(const uint32_t mode) {
|
||||
return { .mode = mode, .pd = 0, .pu = 0, .fast = 0, .input = 1, .ifilt = 1 };
|
||||
}
|
||||
};
|
||||
|
||||
struct Pin {
|
||||
// Pin() = delete;
|
||||
// Pin(const Pin&) = delete;
|
||||
// Pin(Pin&&) = delete;
|
||||
|
||||
constexpr Pin(
|
||||
const uint8_t port,
|
||||
const uint8_t pad,
|
||||
const PinConfig initial_config
|
||||
) : _pin_port { port },
|
||||
_pin_pad { pad },
|
||||
_initial_config { initial_config }
|
||||
{
|
||||
}
|
||||
/*
|
||||
constexpr Pin(
|
||||
const Pin& pin
|
||||
) : _pin_port { pin._pin_port },
|
||||
_pin_pad { pin._pin_pad },
|
||||
_initial_config { pin._initial_config }
|
||||
{
|
||||
}
|
||||
*/
|
||||
void init() const {
|
||||
LPC_SCU->SFSP[_pin_port][_pin_pad] = _initial_config;
|
||||
}
|
||||
|
||||
void mode(const uint_fast16_t mode) const {
|
||||
LPC_SCU->SFSP[_pin_port][_pin_pad] =
|
||||
(LPC_SCU->SFSP[_pin_port][_pin_pad] & ~(7U << 0)) | mode;
|
||||
}
|
||||
|
||||
void configure(const PinConfig config) const {
|
||||
LPC_SCU->SFSP[_pin_port][_pin_pad] = config;
|
||||
}
|
||||
|
||||
uint8_t _pin_port;
|
||||
uint8_t _pin_pad;
|
||||
uint16_t _initial_config;
|
||||
};
|
||||
|
||||
struct GPIO {
|
||||
// GPIO() = delete;
|
||||
// GPIO(const GPIO& gpio) = delete;
|
||||
// GPIO(GPIO&&) = delete;
|
||||
|
||||
constexpr GPIO(
|
||||
const Pin& pin,
|
||||
const ioportid_t gpio_port,
|
||||
const iopadid_t gpio_pad,
|
||||
const uint16_t gpio_mode
|
||||
) : _pin { pin },
|
||||
_gpio_port { gpio_port },
|
||||
_gpio_pad { gpio_pad },
|
||||
_gpio_mode { gpio_mode }
|
||||
{
|
||||
}
|
||||
/*
|
||||
constexpr GPIO(
|
||||
const GPIO& gpio
|
||||
) : _pin { gpio._pin },
|
||||
_gpio_port { gpio._gpio_port },
|
||||
_gpio_pad { gpio._gpio_pad },
|
||||
_gpio_mode { gpio._gpio_mode }
|
||||
{
|
||||
}
|
||||
*/
|
||||
constexpr ioportid_t port() const {
|
||||
return _gpio_port;
|
||||
}
|
||||
|
||||
constexpr iopadid_t pad() const {
|
||||
return _gpio_pad;
|
||||
}
|
||||
|
||||
constexpr Pin pin() const {
|
||||
return _pin;
|
||||
}
|
||||
|
||||
void configure() const {
|
||||
_pin.mode(_gpio_mode);
|
||||
}
|
||||
|
||||
uint_fast16_t mode() const {
|
||||
return _gpio_mode;
|
||||
}
|
||||
|
||||
void set() const {
|
||||
palSetPad(_gpio_port, _gpio_pad);
|
||||
}
|
||||
|
||||
void clear() const {
|
||||
palClearPad(_gpio_port, _gpio_pad);
|
||||
}
|
||||
|
||||
void toggle() const {
|
||||
palTogglePad(_gpio_port, _gpio_pad);
|
||||
}
|
||||
|
||||
void output() const {
|
||||
palSetPadMode(_gpio_port, _gpio_pad, PAL_MODE_OUTPUT_PUSHPULL);
|
||||
}
|
||||
|
||||
void input() const {
|
||||
palSetPadMode(_gpio_port, _gpio_pad, PAL_MODE_INPUT);
|
||||
}
|
||||
|
||||
void write(const bool value) const {
|
||||
palWritePad(_gpio_port, _gpio_pad, value);
|
||||
}
|
||||
|
||||
bool read() const {
|
||||
return palReadPad(_gpio_port, _gpio_pad);
|
||||
}
|
||||
|
||||
bool operator!=(const GPIO& other) const {
|
||||
return (port() != other.port()) || (pad() != other.pad());
|
||||
}
|
||||
|
||||
const Pin _pin;
|
||||
const ioportid_t _gpio_port;
|
||||
const iopadid_t _gpio_pad;
|
||||
const uint16_t _gpio_mode;
|
||||
};
|
||||
|
||||
#endif/*__GPIO_H__*/
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __HACKRF_GPIO_H__
|
||||
#define __HACKRF_GPIO_H__
|
||||
|
||||
#include "pins.hpp"
|
||||
#include "led.hpp"
|
||||
|
||||
#include <array>
|
||||
|
||||
using namespace lpc43xx;
|
||||
|
||||
namespace hackrf {
|
||||
namespace one {
|
||||
|
||||
/* GPIO */
|
||||
|
||||
constexpr GPIO gpio_led_usb = gpio[GPIO2_1];
|
||||
constexpr GPIO gpio_led_rx = gpio[GPIO2_2];
|
||||
constexpr GPIO gpio_led_tx = gpio[GPIO2_8];
|
||||
|
||||
constexpr GPIO gpio_1v8_enable = gpio[GPIO3_6];
|
||||
constexpr GPIO gpio_vregmode = gpio[GPIO3_7];
|
||||
constexpr GPIO gpio_vaa_disable = gpio[GPIO2_9];
|
||||
|
||||
constexpr GPIO gpio_rx_mix_bp = gpio[GPIO2_12];
|
||||
constexpr GPIO gpio_tx_mix_bp = gpio[GPIO2_11];
|
||||
constexpr GPIO gpio_mix_bypass = gpio[GPIO5_16];
|
||||
constexpr GPIO gpio_not_mix_bypass = gpio[GPIO1_0];
|
||||
|
||||
constexpr GPIO gpio_rx = gpio[GPIO5_5];
|
||||
constexpr GPIO gpio_tx = gpio[GPIO5_15];
|
||||
|
||||
constexpr GPIO gpio_lp = gpio[GPIO2_10];
|
||||
constexpr GPIO gpio_hp = gpio[GPIO2_0];
|
||||
|
||||
constexpr GPIO gpio_rx_amp = gpio[GPIO1_11];
|
||||
constexpr GPIO gpio_tx_amp = gpio[GPIO2_15];
|
||||
constexpr GPIO gpio_amp_bypass = gpio[GPIO0_14];
|
||||
constexpr GPIO gpio_not_rx_amp_pwr = gpio[GPIO1_12];
|
||||
constexpr GPIO gpio_not_tx_amp_pwr = gpio[GPIO3_5];
|
||||
|
||||
constexpr GPIO gpio_rffc5072_resetx = gpio[GPIO2_14];
|
||||
constexpr GPIO gpio_rffc5072_select = gpio[GPIO2_13];
|
||||
constexpr GPIO gpio_rffc5072_clock = gpio[GPIO5_6];
|
||||
constexpr GPIO gpio_rffc5072_data = gpio[GPIO3_3];
|
||||
|
||||
constexpr GPIO gpio_max2837_select = gpio[GPIO0_15];
|
||||
constexpr GPIO gpio_max2837_enable = gpio[GPIO2_6];
|
||||
constexpr GPIO gpio_max2837_rxenable = gpio[GPIO2_5];
|
||||
constexpr GPIO gpio_max2837_txenable = gpio[GPIO2_4];
|
||||
|
||||
constexpr GPIO gpio_max5864_select = gpio[GPIO2_7];
|
||||
|
||||
constexpr std::array<GPIO, 3> gpios_baseband_decimation {
|
||||
gpio[GPIO5_12],
|
||||
gpio[GPIO5_13],
|
||||
gpio[GPIO5_14]
|
||||
};
|
||||
constexpr GPIO gpio_baseband_q_invert = gpio[GPIO0_13];
|
||||
|
||||
/* LEDs */
|
||||
|
||||
constexpr LED led_usb { gpio_led_usb };
|
||||
constexpr LED led_rx { gpio_led_rx };
|
||||
constexpr LED led_tx { gpio_led_tx };
|
||||
|
||||
} /* namespace one */
|
||||
} /* namespace hackrf */
|
||||
|
||||
#endif/*__HACKRF_GPIO_H__*/
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 "hackrf_hal.hpp"
|
||||
|
||||
#include "lpc43xx_cpp.hpp"
|
||||
|
||||
using namespace lpc43xx;
|
||||
|
||||
namespace hackrf {
|
||||
namespace one {
|
||||
|
||||
void reset() {
|
||||
/* "The reset delay is counted in IRC clock cycles. If the core frequency
|
||||
* CCLK is much higher than the IRC frequency, add a software delay of
|
||||
* fCCLK/fIRC clock cycles between resetting and accessing any of the
|
||||
* peripheral blocks."
|
||||
*/
|
||||
rgu::reset_mask(
|
||||
/* Don't reset SCU, may trip up SPIFI pins if running from SPIFI
|
||||
* memory.
|
||||
*/
|
||||
/*rgu::Reset::SCU */
|
||||
rgu::Reset::LCD
|
||||
| rgu::Reset::USB0
|
||||
| rgu::Reset::USB1
|
||||
| rgu::Reset::DMA
|
||||
| rgu::Reset::SDIO
|
||||
| rgu::Reset::EMC
|
||||
| rgu::Reset::ETHERNET
|
||||
| rgu::Reset::GPIO
|
||||
| rgu::Reset::TIMER0
|
||||
| rgu::Reset::TIMER1
|
||||
| rgu::Reset::TIMER2
|
||||
| rgu::Reset::TIMER3
|
||||
| rgu::Reset::RITIMER
|
||||
| rgu::Reset::SCT
|
||||
| rgu::Reset::MOTOCONPWM
|
||||
| rgu::Reset::QEI
|
||||
| rgu::Reset::ADC0
|
||||
| rgu::Reset::ADC1
|
||||
| rgu::Reset::DAC
|
||||
| rgu::Reset::UART0
|
||||
| rgu::Reset::UART1
|
||||
| rgu::Reset::UART2
|
||||
| rgu::Reset::UART3
|
||||
| rgu::Reset::I2C0
|
||||
| rgu::Reset::I2C1
|
||||
| rgu::Reset::SSP0
|
||||
| rgu::Reset::SSP1
|
||||
| rgu::Reset::I2S
|
||||
/* Don't reset SPIFI if running from SPIFI memory */
|
||||
/*| rgu::Reset::SPIFI*/
|
||||
| rgu::Reset::CAN1
|
||||
| rgu::Reset::CAN0
|
||||
/* Don't reset M0 if that's the core we're running on! */
|
||||
/*| rgu::Reset::M0APP */
|
||||
| rgu::Reset::SGPIO
|
||||
| rgu::Reset::SPI
|
||||
);
|
||||
}
|
||||
|
||||
} /* namespace one */
|
||||
} /* namespace hackrf */
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __HACKRF_HAL_H__
|
||||
#define __HACKRF_HAL_H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "adc.hpp"
|
||||
|
||||
using namespace lpc43xx;
|
||||
|
||||
namespace hackrf {
|
||||
namespace one {
|
||||
|
||||
/* Clocks */
|
||||
|
||||
using ClockFrequency = uint32_t;
|
||||
|
||||
constexpr ClockFrequency si5351_xtal_f = 25000000U;
|
||||
constexpr ClockFrequency si5351_clkin_f = 10000000U;
|
||||
|
||||
/* TODO: Use this many other places. */
|
||||
/* TODO: M4/M0 and peripheral rates may be more PortaPack-specific? Move out
|
||||
* of HackRF header? */
|
||||
constexpr ClockFrequency base_m4_clk_f = 200000000U;
|
||||
constexpr ClockFrequency base_m0_clk_f = base_m4_clk_f;
|
||||
constexpr ClockFrequency base_apb3_clk_f = base_m4_clk_f;
|
||||
constexpr ClockFrequency ssp1_pclk_f = base_m4_clk_f;
|
||||
|
||||
constexpr ClockFrequency max5864_spi_f = 20000000U;
|
||||
constexpr ClockFrequency max2837_spi_f = 20000000U;
|
||||
|
||||
constexpr ClockFrequency rffc5072_reference_f = 50000000U;
|
||||
constexpr ClockFrequency max2837_reference_f = 50000000U;
|
||||
constexpr ClockFrequency mcu_clkin_f = 40000000U;
|
||||
|
||||
constexpr uint8_t si5351_i2c_address = 0x60;
|
||||
|
||||
/* Clock Generator */
|
||||
|
||||
constexpr size_t clock_generator_output_codec = 0;
|
||||
constexpr size_t clock_generator_output_cpld = 1;
|
||||
constexpr size_t clock_generator_output_sgpio = 2;
|
||||
constexpr size_t clock_generator_output_clkout = 3;
|
||||
constexpr size_t clock_generator_output_first_if = 4;
|
||||
constexpr size_t clock_generator_output_second_if = 5;
|
||||
constexpr size_t clock_generator_output_mcu_clkin = 7;
|
||||
|
||||
/* ADC0 */
|
||||
|
||||
constexpr adc::ADC adc0 { LPC_ADC0 };
|
||||
|
||||
/* ADC1 */
|
||||
|
||||
constexpr adc::ADC adc1 { LPC_ADC1 };
|
||||
|
||||
void reset();
|
||||
|
||||
} /* namespace one */
|
||||
} /* namespace hackrf */
|
||||
|
||||
#endif/*__HACKRF_HAL_H__*/
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 "i2c_pp.hpp"
|
||||
|
||||
void I2C::start(const I2CConfig& config) {
|
||||
i2cStart(_driver, &config);
|
||||
}
|
||||
|
||||
void I2C::stop() {
|
||||
i2cStop(_driver);
|
||||
}
|
||||
|
||||
bool I2C::transfer(
|
||||
const address_t slave_address,
|
||||
const uint8_t* const data_tx, const size_t count_tx,
|
||||
uint8_t* const data_rx, const size_t count_rx,
|
||||
systime_t timeout
|
||||
) {
|
||||
i2cAcquireBus(_driver);
|
||||
const msg_t status = i2cMasterTransmitTimeout(
|
||||
_driver, slave_address, data_tx, count_tx, data_rx, count_rx, timeout
|
||||
);
|
||||
i2cReleaseBus(_driver);
|
||||
return (status == RDY_OK);
|
||||
}
|
||||
|
||||
bool I2C::receive(
|
||||
const address_t slave_address,
|
||||
uint8_t* const data, const size_t count,
|
||||
systime_t timeout
|
||||
) {
|
||||
i2cAcquireBus(_driver);
|
||||
const msg_t status = i2cMasterReceiveTimeout(
|
||||
_driver, slave_address, data, count, timeout
|
||||
);
|
||||
i2cReleaseBus(_driver);
|
||||
return (status == RDY_OK);
|
||||
}
|
||||
|
||||
bool I2C::transmit(
|
||||
const address_t slave_address,
|
||||
const uint8_t* const data, const size_t count,
|
||||
systime_t timeout
|
||||
) {
|
||||
return transfer(slave_address, data, count, NULL, 0, timeout);
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __I2C_PP_H__
|
||||
#define __I2C_PP_H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
|
||||
struct I2CClockConfig {
|
||||
float clock_source_f;
|
||||
float bus_f;
|
||||
float high_period_ns;
|
||||
|
||||
constexpr I2CClockConfig(
|
||||
float clock_source_f,
|
||||
float bus_f,
|
||||
float high_period_ns
|
||||
) : clock_source_f(clock_source_f),
|
||||
bus_f(bus_f),
|
||||
high_period_ns(high_period_ns)
|
||||
{
|
||||
}
|
||||
|
||||
static constexpr float period_ns(const float f) {
|
||||
return 1e9 / f;
|
||||
}
|
||||
|
||||
constexpr uint32_t i2c_period_count() {
|
||||
return period_ns(bus_f) / period_ns(clock_source_f) + 0.5f;
|
||||
}
|
||||
|
||||
constexpr uint32_t i2c_high_count() {
|
||||
return high_period_ns / period_ns(clock_source_f) + 0.5f;
|
||||
}
|
||||
|
||||
constexpr uint32_t i2c_low_count() {
|
||||
return i2c_period_count() - i2c_high_count();
|
||||
}
|
||||
};
|
||||
|
||||
class I2C {
|
||||
public:
|
||||
using address_t = uint8_t;
|
||||
|
||||
constexpr I2C(I2CDriver* const driver) :
|
||||
_driver(driver) {
|
||||
}
|
||||
|
||||
void start(const I2CConfig& config);
|
||||
void stop();
|
||||
|
||||
bool receive(
|
||||
const address_t slave_address,
|
||||
uint8_t* const data, const size_t count,
|
||||
const systime_t timeout = TIME_INFINITE
|
||||
);
|
||||
|
||||
bool transmit(
|
||||
const address_t slave_address,
|
||||
const uint8_t* const data, const size_t count,
|
||||
const systime_t timeout = TIME_INFINITE
|
||||
);
|
||||
|
||||
private:
|
||||
I2CDriver* const _driver;
|
||||
|
||||
bool transfer(
|
||||
const address_t slave_address,
|
||||
const uint8_t* const data_tx, const size_t count_tx,
|
||||
uint8_t* const data_rx, const size_t count_rx,
|
||||
const systime_t timeout
|
||||
);
|
||||
};
|
||||
|
||||
#endif/*__I2C_PP_H__*/
|
||||
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __I2S_H__
|
||||
#define __I2S_H__
|
||||
|
||||
#include "hal.h"
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace lpc43xx {
|
||||
namespace i2s {
|
||||
|
||||
enum class WordWidth {
|
||||
Bits8 = 0x0,
|
||||
Bits16 = 0x1,
|
||||
Bits32 = 0x3,
|
||||
};
|
||||
|
||||
enum class ClockSelect {
|
||||
FractionalDivider = 0x0,
|
||||
BaseAudioClkOrExternalMCLK = 0x01,
|
||||
OtherMCLK = 0x2,
|
||||
};
|
||||
|
||||
struct DAO {
|
||||
WordWidth wordwidth;
|
||||
uint32_t mono;
|
||||
uint32_t stop;
|
||||
uint32_t reset;
|
||||
uint32_t ws_sel;
|
||||
uint32_t ws_halfperiod;
|
||||
uint32_t mute;
|
||||
|
||||
constexpr operator uint32_t() const {
|
||||
return
|
||||
((toUType(wordwidth) & 3) << 0)
|
||||
| ((mono & 1) << 2)
|
||||
| ((stop & 1) << 3)
|
||||
| ((reset & 1) << 4)
|
||||
| ((ws_sel & 1) << 5)
|
||||
| ((ws_halfperiod & 0x1ff) << 6)
|
||||
| ((mute & 1) << 15)
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
struct DAI {
|
||||
WordWidth wordwidth;
|
||||
uint32_t mono;
|
||||
uint32_t stop;
|
||||
uint32_t reset;
|
||||
uint32_t ws_sel;
|
||||
uint32_t ws_halfperiod;
|
||||
|
||||
constexpr operator uint32_t() const {
|
||||
return
|
||||
((toUType(wordwidth) & 3) << 0)
|
||||
| ((mono & 1) << 2)
|
||||
| ((stop & 1) << 3)
|
||||
| ((reset & 1) << 4)
|
||||
| ((ws_sel & 1) << 5)
|
||||
| ((ws_halfperiod & 0x1ff) << 6)
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
struct MCLKRate {
|
||||
uint32_t x_divider;
|
||||
uint32_t y_divider;
|
||||
|
||||
constexpr operator uint32_t() const {
|
||||
return
|
||||
((y_divider & 0xff) << 0)
|
||||
| ((x_divider & 0xff) << 8)
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
struct BitRate {
|
||||
uint32_t bitrate;
|
||||
|
||||
constexpr operator uint32_t() const {
|
||||
return ((bitrate & 0x3f) << 0);
|
||||
}
|
||||
};
|
||||
|
||||
struct Mode {
|
||||
ClockSelect clksel;
|
||||
uint32_t four_pin;
|
||||
uint32_t mclk_out_en;
|
||||
|
||||
constexpr operator uint32_t() const {
|
||||
return
|
||||
((toUType(clksel) & 3) << 0)
|
||||
| ((four_pin & 1) << 2)
|
||||
| ((mclk_out_en & 1) << 3)
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
struct DMA {
|
||||
uint32_t rx_enable;
|
||||
uint32_t tx_enable;
|
||||
size_t rx_depth;
|
||||
size_t tx_depth;
|
||||
|
||||
constexpr operator uint32_t() const {
|
||||
return
|
||||
((rx_enable & 1) << 0)
|
||||
| ((tx_enable & 1) << 1)
|
||||
| ((rx_depth & 0xf) << 8)
|
||||
| ((tx_depth & 0xf) << 16)
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
struct ConfigTX {
|
||||
uint32_t dao;
|
||||
uint32_t txrate;
|
||||
uint32_t txbitrate;
|
||||
uint32_t txmode;
|
||||
};
|
||||
|
||||
struct ConfigRX {
|
||||
uint32_t dai;
|
||||
uint32_t rxrate;
|
||||
uint32_t rxbitrate;
|
||||
uint32_t rxmode;
|
||||
};
|
||||
|
||||
struct ConfigDMA {
|
||||
uint32_t dma1;
|
||||
uint32_t dma2;
|
||||
};
|
||||
|
||||
template<uint32_t BaseAddress>
|
||||
class I2S {
|
||||
public:
|
||||
static constexpr LPC_I2S_Type* Peripheral = reinterpret_cast<LPC_I2S_Type*>(BaseAddress);
|
||||
|
||||
static void configure(
|
||||
const ConfigTX& config_tx,
|
||||
const ConfigRX& config_rx
|
||||
) {
|
||||
reset();
|
||||
|
||||
/* I2S operates in master mode, use PLL0AUDIO as MCLK source for TX. */
|
||||
/* NOTE: Documentation of CREG6 is quite confusing. Refer to "I2S clocking and
|
||||
* pin connections" and other I2S diagrams for more clarity.
|
||||
*/
|
||||
if( Peripheral == LPC_I2S0 ) {
|
||||
LPC_CREG->CREG6 |=
|
||||
(1U << 12)
|
||||
| (1U << 13)
|
||||
;
|
||||
}
|
||||
if( Peripheral == LPC_I2S1 ) {
|
||||
LPC_CREG->CREG6 |=
|
||||
(1U << 14)
|
||||
| (1U << 15)
|
||||
;
|
||||
}
|
||||
|
||||
Peripheral->DAO = config_tx.dao;
|
||||
Peripheral->TXRATE = config_tx.txrate;
|
||||
Peripheral->TXBITRATE = config_tx.txbitrate;
|
||||
Peripheral->TXMODE = config_tx.txmode;
|
||||
|
||||
Peripheral->DAI = config_rx.dai;
|
||||
Peripheral->RXRATE = config_rx.rxrate;
|
||||
Peripheral->RXBITRATE = config_rx.rxbitrate;
|
||||
Peripheral->RXMODE = config_rx.rxmode;
|
||||
}
|
||||
|
||||
static void configure(
|
||||
const ConfigTX& config_tx,
|
||||
const ConfigRX& config_rx,
|
||||
const ConfigDMA& config_dma
|
||||
) {
|
||||
configure(config_tx, config_rx);
|
||||
|
||||
Peripheral->DMA1 = config_dma.dma1;
|
||||
Peripheral->DMA2 = config_dma.dma2;
|
||||
}
|
||||
|
||||
static void rx_start() {
|
||||
Peripheral->DAI &= ~(1U << 3);
|
||||
}
|
||||
|
||||
static void rx_stop() {
|
||||
Peripheral->DAI |= (1U << 3);
|
||||
}
|
||||
|
||||
static void tx_start() {
|
||||
Peripheral->DAO &= ~(1U << 3);
|
||||
}
|
||||
|
||||
static void tx_stop() {
|
||||
Peripheral->DAO |= (1U << 3);
|
||||
}
|
||||
|
||||
static void tx_mute() {
|
||||
Peripheral->DAO |= (1U << 15);
|
||||
}
|
||||
|
||||
static void tx_unmute() {
|
||||
Peripheral->DAO &= ~(1U << 15);
|
||||
}
|
||||
|
||||
private:
|
||||
static void reset() {
|
||||
Peripheral->DAO |= (1U << 4);
|
||||
Peripheral->DAI |= (1U << 4);
|
||||
}
|
||||
};
|
||||
|
||||
using i2s0 = I2S<LPC_I2S0_BASE>;
|
||||
using i2s1 = I2S<LPC_I2S1_BASE>;
|
||||
|
||||
} /* namespace i2s */
|
||||
} /* namespace lpc43xx */
|
||||
|
||||
#endif/*__I2S_H__*/
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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 "jtag.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
namespace jtag {
|
||||
|
||||
uint32_t JTAG::shift(const size_t count, uint32_t value) {
|
||||
for(size_t i=0; i<count; i++) {
|
||||
const auto tdo = target.clock(
|
||||
(i == (count - 1)) ? 1 : 0,
|
||||
value & 1
|
||||
);
|
||||
value >>= 1;
|
||||
value |= tdo << (count - 1);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
} /* namespace jtag */
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __JTAG_H__
|
||||
#define __JTAG_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
#include <bitset>
|
||||
|
||||
namespace jtag {
|
||||
|
||||
class Target {
|
||||
public:
|
||||
using bit_t = uint_fast8_t;
|
||||
|
||||
virtual ~Target() {
|
||||
}
|
||||
|
||||
virtual void delay(const size_t n) = 0;
|
||||
virtual jtag::Target::bit_t clock(
|
||||
const jtag::Target::bit_t tms_value,
|
||||
const jtag::Target::bit_t tdi_value
|
||||
) = 0;
|
||||
};
|
||||
|
||||
class JTAG {
|
||||
public:
|
||||
constexpr JTAG(
|
||||
Target& target
|
||||
) : target(target)
|
||||
{
|
||||
}
|
||||
|
||||
void reset() {
|
||||
/* ??? -> Test-Logic-Reset */
|
||||
for(size_t i=0; i<8; i++) {
|
||||
target.clock(1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void run_test_idle() {
|
||||
/* Test-Logic-Reset -> Run-Test/Idle */
|
||||
target.clock(0, 0);
|
||||
}
|
||||
|
||||
void runtest_tck(const size_t count) {
|
||||
target.delay(count);
|
||||
}
|
||||
|
||||
uint32_t shift_ir(const size_t count, const uint32_t value) {
|
||||
/* Run-Test/Idle -> Select-DR-Scan -> Select-IR-Scan */
|
||||
target.clock(1, 0);
|
||||
target.clock(1, 0);
|
||||
/* Scan -> Capture -> Shift */
|
||||
target.clock(0, 0);
|
||||
target.clock(0, 0);
|
||||
|
||||
const auto result = shift(count, value);
|
||||
|
||||
/* Exit1 -> Update */
|
||||
target.clock(1, 0);
|
||||
/* Update -> Run-Test/Idle */
|
||||
target.clock(0, 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t shift_dr(const size_t count, const uint32_t value) {
|
||||
/* Run-Test/Idle -> Select-DR-Scan */
|
||||
target.clock(1, 0);
|
||||
/* Scan -> Capture -> Shift */
|
||||
target.clock(0, 0);
|
||||
target.clock(0, 0);
|
||||
|
||||
const auto result = shift(count, value);
|
||||
|
||||
/* Exit1 -> Update */
|
||||
target.clock(1, 0);
|
||||
/* Update -> Run-Test/Idle */
|
||||
target.clock(0, 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template<size_t N>
|
||||
void shift_dr(std::bitset<N>& bits) {
|
||||
/* Run-Test/Idle -> Select-DR-Scan */
|
||||
target.clock(1, 0);
|
||||
/* Scan -> Capture -> Shift */
|
||||
target.clock(0, 0);
|
||||
target.clock(0, 0);
|
||||
|
||||
for(size_t i=0; i<bits.size(); i++) {
|
||||
bits[i] = target.clock(
|
||||
(i == (bits.size() - 1)) ? 1 : 0,
|
||||
bits[i]
|
||||
);
|
||||
}
|
||||
|
||||
/* Exit1 -> Update */
|
||||
target.clock(1, 0);
|
||||
/* Update -> Run-Test/Idle */
|
||||
target.clock(0, 0);
|
||||
}
|
||||
|
||||
private:
|
||||
Target& target;
|
||||
|
||||
uint32_t shift(const size_t count, uint32_t value);
|
||||
};
|
||||
|
||||
} /* namespace jtag */
|
||||
|
||||
#endif/*__JTAG_H__*/
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __JTAG_TARGET_GPIO_H__
|
||||
#define __JTAG_TARGET_GPIO_H__
|
||||
|
||||
#include "jtag.hpp"
|
||||
|
||||
#include <ch.h>
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace jtag {
|
||||
|
||||
class GPIOTarget : public Target {
|
||||
public:
|
||||
// Tightly control how this object can be constructor or copied, since
|
||||
// it initializes GPIOs in the constructor. I don't want it re-
|
||||
// initializing a bunch as the object gets passed around. So don't let
|
||||
// it get passed around...
|
||||
/*
|
||||
GPIOTarget() = delete;
|
||||
GPIOTarget(const GPIOTarget&) = delete;
|
||||
GPIOTarget(GPIOTarget&&) = delete;
|
||||
GPIOTarget& operator=(const GPIOTarget&) = delete;
|
||||
GPIOTarget& operator=(GPIOTarget&&) = delete;
|
||||
*/
|
||||
GPIOTarget(
|
||||
GPIO gpio_tck,
|
||||
GPIO gpio_tms,
|
||||
GPIO gpio_tdi,
|
||||
GPIO gpio_tdo
|
||||
) : gpio_tck { gpio_tck },
|
||||
gpio_tms { gpio_tms },
|
||||
gpio_tdi { gpio_tdi },
|
||||
gpio_tdo { gpio_tdo }
|
||||
{
|
||||
gpio_tdi.write(1);
|
||||
gpio_tdi.output();
|
||||
gpio_tdi.configure();
|
||||
|
||||
gpio_tms.write(1);
|
||||
gpio_tms.output();
|
||||
gpio_tms.configure();
|
||||
|
||||
gpio_tck.write(0);
|
||||
gpio_tck.output();
|
||||
gpio_tck.configure();
|
||||
|
||||
gpio_tdo.input();
|
||||
gpio_tdo.configure();
|
||||
}
|
||||
|
||||
~GPIOTarget() {
|
||||
gpio_tdi.input();
|
||||
gpio_tms.input();
|
||||
gpio_tck.input();
|
||||
}
|
||||
|
||||
void delay(const size_t clocks) override {
|
||||
/* TODO: Use more precise timing mechanism, using the frequency
|
||||
* specified by SVF file.
|
||||
*/
|
||||
halPolledDelay(clocks * systicks_per_tck);
|
||||
}
|
||||
|
||||
Target::bit_t clock(
|
||||
const Target::bit_t tms_value,
|
||||
const Target::bit_t tdi_value
|
||||
) override {
|
||||
/* TODO: Use more precise timing mechanism, using the frequency
|
||||
* specified by SVF file.
|
||||
*/
|
||||
const auto result = tdo();
|
||||
tms(tms_value);
|
||||
tdi(tdi_value);
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
tck(1);
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
tck(0);
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
/* At 200MHz, one 18MHz cycle is 11 systicks. */
|
||||
static constexpr size_t systicks_per_tck = 11;
|
||||
|
||||
GPIO gpio_tck;
|
||||
GPIO gpio_tms;
|
||||
GPIO gpio_tdi;
|
||||
GPIO gpio_tdo;
|
||||
|
||||
void tck(const Target::bit_t value) {
|
||||
gpio_tck.write(value);
|
||||
}
|
||||
|
||||
void tdi(const Target::bit_t value) {
|
||||
gpio_tdi.write(value);
|
||||
}
|
||||
|
||||
void tms(const bit_t value) {
|
||||
gpio_tms.write(value);
|
||||
}
|
||||
|
||||
Target::bit_t tdo() {
|
||||
return gpio_tdo.read();
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace jtag */
|
||||
|
||||
#endif/*__JTAG_TARGET_GPIO_H__*/
|
||||
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 "lcd_ili9341.hpp"
|
||||
|
||||
#include "portapack_io.hpp"
|
||||
using namespace portapack;
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
#include "ch.h"
|
||||
|
||||
namespace lcd {
|
||||
|
||||
namespace {
|
||||
|
||||
void lcd_reset() {
|
||||
io.lcd_reset_state(false);
|
||||
chThdSleepMilliseconds(1);
|
||||
io.lcd_reset_state(true);
|
||||
chThdSleepMilliseconds(10);
|
||||
io.lcd_reset_state(false);
|
||||
chThdSleepMilliseconds(120);
|
||||
}
|
||||
|
||||
void lcd_init() {
|
||||
// LCDs are configured for IM[2:0] = 001
|
||||
// 8080-I system, 16-bit parallel bus
|
||||
|
||||
//
|
||||
// 0x3a: DBI[2:0] = 101
|
||||
// MDT[1:0] = XX (if not in 18-bit mode, right?)
|
||||
|
||||
// Power control B
|
||||
// 0
|
||||
// PCEQ=1, DRV_ena=0, Power control=3
|
||||
io.lcd_data_write_command_and_data(0xCF, { 0x00, 0xD9, 0x30 });
|
||||
|
||||
// Power on sequence control
|
||||
io.lcd_data_write_command_and_data(0xED, { 0x64, 0x03, 0x12, 0x81 });
|
||||
|
||||
// Driver timing control A
|
||||
io.lcd_data_write_command_and_data(0xE8, { 0x85, 0x10, 0x78 });
|
||||
|
||||
// Power control A
|
||||
io.lcd_data_write_command_and_data(0xCB, { 0x39, 0x2C, 0x00, 0x34, 0x02 });
|
||||
|
||||
// Pump ratio control
|
||||
io.lcd_data_write_command_and_data(0xF7, { 0x20 });
|
||||
|
||||
// Driver timing control B
|
||||
io.lcd_data_write_command_and_data(0xEA, { 0x00, 0x00 });
|
||||
|
||||
io.lcd_data_write_command_and_data(0xB1, { 0x00, 0x1B });
|
||||
|
||||
// Blanking Porch Control
|
||||
// VFP = 0b0000010 = 2 (number of HSYNC of vertical front porch)
|
||||
// VBP = 0b0000010 = 2 (number of HSYNC of vertical back porch)
|
||||
// HFP = 0b0001010 = 10 (number of DOTCLOCK of horizontal front porch)
|
||||
// HBP = 0b0010100 = 20 (number of DOTCLOCK of horizontal back porch)
|
||||
io.lcd_data_write_command_and_data(0xB5, { 0x02, 0x02, 0x0a, 0x14 });
|
||||
|
||||
// Display Function Control
|
||||
// PT[1:0] = 0b10
|
||||
// PTG[1:0] = 0b10
|
||||
// ISC[3:0] = 0b0010 (scan cycle interval of gate driver: 5 frames)
|
||||
// SM = 0 (gate driver pin arrangement in combination with GS)
|
||||
// SS = 1 (source output scan direction S720 -> S1)
|
||||
// GS = 0 (gate output scan direction G1 -> G320)
|
||||
// REV = 1 (normally white)
|
||||
// NL = 0b100111 (default)
|
||||
// PCDIV = 0b000000 (default?)
|
||||
io.lcd_data_write_command_and_data(0xB6, { 0x0A, 0xA2, 0x27, 0x00 });
|
||||
|
||||
// Power Control 1
|
||||
//VRH[5:0]
|
||||
io.lcd_data_write_command_and_data(0xC0, { 0x1B });
|
||||
|
||||
// Power Control 2
|
||||
//SAP[2:0];BT[3:0]
|
||||
io.lcd_data_write_command_and_data(0xC1, { 0x12 });
|
||||
|
||||
// VCOM Control 1
|
||||
io.lcd_data_write_command_and_data(0xC5, { 0x32, 0x3C });
|
||||
|
||||
// VCOM Control 2
|
||||
io.lcd_data_write_command_and_data(0xC7, { 0x9B });
|
||||
|
||||
// Memory Access Control
|
||||
// Invert X and Y memory access order, so upper-left of
|
||||
// screen is (0,0) when writing to display.
|
||||
io.lcd_data_write_command_and_data(0x36, {
|
||||
(1 << 7) | // MY=1
|
||||
(1 << 6) | // MX=1
|
||||
(0 << 5) | // MV=0
|
||||
(1 << 4) | // ML=1: reverse vertical refresh to simplify scrolling logic
|
||||
(1 << 3) // BGR=1: For Kingtech LCD, BGR filter.
|
||||
});
|
||||
|
||||
// COLMOD: Pixel Format Set
|
||||
// DPI=101 (16 bits/pixel), DBI=101 (16 bits/pixel)
|
||||
io.lcd_data_write_command_and_data(0x3A, { 0x55 });
|
||||
|
||||
//io.lcd_data_write_command_and_data(0xF6, { 0x01, 0x30 });
|
||||
// WEMODE=1 (reset column and page number on overflow)
|
||||
// MDT[1:0]
|
||||
// EPF[1:0]=00 (use channel MSB for LSB)
|
||||
// RIM=0 (If COLMOD[6:4]=101 (65k color), 16-bit RGB interface (1 transfer/pixel))
|
||||
// RM=0 (system interface/VSYNC interface)
|
||||
// DM[1:0]=00 (internal clock operation)
|
||||
// ENDIAN=0 (doesn't matter with 16-bit interface)
|
||||
io.lcd_data_write_command_and_data(0xF6, { 0x01, 0x30, 0x00 });
|
||||
|
||||
// 3Gamma Function Disable
|
||||
io.lcd_data_write_command_and_data(0xF2, { 0x00 });
|
||||
|
||||
// Gamma curve selected
|
||||
io.lcd_data_write_command_and_data(0x26, { 0x01 });
|
||||
|
||||
// Set Gamma
|
||||
io.lcd_data_write_command_and_data(0xE0, {
|
||||
0x0F, 0x1D, 0x19, 0x0E, 0x10, 0x07, 0x4C, 0x63,
|
||||
0x3F, 0x03, 0x0D, 0x00, 0x26, 0x24, 0x04
|
||||
});
|
||||
|
||||
// Set Gamma
|
||||
io.lcd_data_write_command_and_data(0xE1, {
|
||||
0x00, 0x1C, 0x1F, 0x02, 0x0F, 0x03, 0x35, 0x25,
|
||||
0x47, 0x04, 0x0C, 0x0B, 0x29, 0x2F, 0x05
|
||||
});
|
||||
|
||||
// Exit Sleep
|
||||
io.lcd_data_write_command_and_data(0x11, {});
|
||||
chThdSleepMilliseconds(120);
|
||||
|
||||
// Display on
|
||||
io.lcd_data_write_command_and_data(0x29, {});
|
||||
|
||||
// Turn on Tearing Effect Line (TE) output signal.
|
||||
io.lcd_data_write_command_and_data(0x35, { 0b00000000 });
|
||||
}
|
||||
|
||||
void lcd_set(const uint_fast8_t command, const uint_fast16_t start, const uint_fast16_t end) {
|
||||
io.lcd_data_write_command_and_data(command, {
|
||||
static_cast<uint8_t>(start >> 8), static_cast<uint8_t>(start & 0xff),
|
||||
static_cast<uint8_t>(end >> 8), static_cast<uint8_t>(end & 0xff)
|
||||
});
|
||||
}
|
||||
|
||||
void lcd_ramwr_start() {
|
||||
io.lcd_data_write_command_and_data(0x2c, {});
|
||||
}
|
||||
|
||||
void lcd_caset(const uint_fast16_t start_column, uint_fast16_t end_column) {
|
||||
lcd_set(0x2a, start_column, end_column);
|
||||
}
|
||||
|
||||
void lcd_paset(const uint_fast16_t start_page, const uint_fast16_t end_page) {
|
||||
lcd_set(0x2b, start_page, end_page);
|
||||
}
|
||||
|
||||
void lcd_start_ram_write(
|
||||
const ui::Point p,
|
||||
const ui::Size s
|
||||
) {
|
||||
lcd_caset(p.x, p.x + s.w - 1);
|
||||
lcd_paset(p.y, p.y + s.h - 1);
|
||||
lcd_ramwr_start();
|
||||
}
|
||||
|
||||
void lcd_start_ram_write(
|
||||
const ui::Rect& r
|
||||
) {
|
||||
lcd_start_ram_write(r.pos, r.size);
|
||||
}
|
||||
|
||||
void lcd_vertical_scrolling_definition(
|
||||
const uint_fast16_t top_fixed_area,
|
||||
const uint_fast16_t vertical_scrolling_area,
|
||||
const uint_fast16_t bottom_fixed_area
|
||||
) {
|
||||
io.lcd_data_write_command_and_data(0x33, {
|
||||
static_cast<uint8_t>(top_fixed_area >> 8),
|
||||
static_cast<uint8_t>(top_fixed_area & 0xff),
|
||||
static_cast<uint8_t>(vertical_scrolling_area >> 8),
|
||||
static_cast<uint8_t>(vertical_scrolling_area & 0xff),
|
||||
static_cast<uint8_t>(bottom_fixed_area >> 8),
|
||||
static_cast<uint8_t>(bottom_fixed_area & 0xff)
|
||||
});
|
||||
}
|
||||
|
||||
void lcd_vertical_scrolling_start_address(
|
||||
const uint_fast16_t vertical_scrolling_pointer
|
||||
) {
|
||||
io.lcd_data_write_command_and_data(0x37, {
|
||||
static_cast<uint8_t>(vertical_scrolling_pointer >> 8),
|
||||
static_cast<uint8_t>(vertical_scrolling_pointer & 0xff)
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ILI9341::init() {
|
||||
lcd_reset();
|
||||
lcd_init();
|
||||
|
||||
io.lcd_backlight(1);
|
||||
}
|
||||
|
||||
void ILI9341::fill_rectangle(ui::Rect r, const ui::Color c) {
|
||||
const auto r_clipped = r.intersect(screen_rect());
|
||||
if( !r_clipped.is_empty() ) {
|
||||
lcd_start_ram_write(r_clipped);
|
||||
size_t count = r_clipped.size.w * r_clipped.size.h;
|
||||
io.lcd_write_pixels(c, count);
|
||||
}
|
||||
}
|
||||
|
||||
void ILI9341::fill_circle(
|
||||
const ui::Point center,
|
||||
const ui::Dim radius,
|
||||
const ui::Color foreground,
|
||||
const ui::Color background
|
||||
) {
|
||||
const uint32_t radius2 = radius * radius;
|
||||
for(int32_t y=-radius; y<radius; y++) {
|
||||
const int32_t y2 = y * y;
|
||||
for(int32_t x=-radius; x<radius; x++) {
|
||||
const int32_t x2 = x * x;
|
||||
const uint32_t d2 = x2 + y2;
|
||||
const bool inside = d2 < radius2;
|
||||
const auto color = inside ? foreground : background;
|
||||
draw_pixel({
|
||||
static_cast<ui::Coord>(x + center.x),
|
||||
static_cast<ui::Coord>(y + center.y)
|
||||
}, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ILI9341::draw_pixel(
|
||||
const ui::Point p,
|
||||
const ui::Color color
|
||||
) {
|
||||
if( screen_rect().contains(p) ) {
|
||||
lcd_start_ram_write(p, { 1, 1 });
|
||||
io.lcd_write_pixel(color);
|
||||
}
|
||||
}
|
||||
|
||||
void ILI9341::draw_pixels(
|
||||
const ui::Rect r,
|
||||
const ui::Color* const colors,
|
||||
const size_t count
|
||||
) {
|
||||
/* TODO: Assert that rectangle width x height < count */
|
||||
lcd_start_ram_write(r.pos, r.size);
|
||||
io.lcd_write_pixels(colors, count);
|
||||
}
|
||||
|
||||
void ILI9341::draw_glyph(
|
||||
const ui::Point p,
|
||||
const ui::Glyph& glyph,
|
||||
const ui::Color foreground,
|
||||
const ui::Color background
|
||||
) {
|
||||
lcd_start_ram_write(p, glyph.size());
|
||||
|
||||
const size_t count = glyph.w() * glyph.h();
|
||||
const auto pixels = glyph.pixels();
|
||||
for(size_t i=0; i<count; i++) {
|
||||
const auto pixel = pixels[i >> 3] & (1U << (i & 0x7));
|
||||
io.lcd_write_pixel(pixel ? foreground : background);
|
||||
}
|
||||
}
|
||||
|
||||
void ILI9341::scroll_set_area(
|
||||
const ui::Coord top_y,
|
||||
const ui::Coord bottom_y
|
||||
) {
|
||||
scroll_state.top_area = top_y;
|
||||
scroll_state.bottom_area = height() - bottom_y;
|
||||
scroll_state.height = bottom_y - top_y;
|
||||
lcd_vertical_scrolling_definition(scroll_state.top_area, scroll_state.height, scroll_state.bottom_area);
|
||||
}
|
||||
|
||||
ui::Coord ILI9341::scroll_set_position(
|
||||
const ui::Coord position
|
||||
) {
|
||||
scroll_state.current_position = position % scroll_state.height;
|
||||
const uint_fast16_t address = scroll_state.top_area + scroll_state.current_position;
|
||||
lcd_vertical_scrolling_start_address(address);
|
||||
return address;
|
||||
}
|
||||
|
||||
ui::Coord ILI9341::scroll(const int32_t delta) {
|
||||
return scroll_set_position(scroll_state.current_position + scroll_state.height - delta);
|
||||
}
|
||||
|
||||
ui::Coord ILI9341::scroll_area_y(const ui::Coord y) const {
|
||||
const auto wrapped_y = (scroll_state.current_position + y) % scroll_state.height;
|
||||
return wrapped_y + scroll_state.top_area;
|
||||
}
|
||||
|
||||
void ILI9341::scroll_disable() {
|
||||
lcd_vertical_scrolling_definition(0, height(), 0);
|
||||
lcd_vertical_scrolling_start_address(0);
|
||||
}
|
||||
|
||||
} /* namespace lcd */
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __LCD_ILI9341_H__
|
||||
#define __LCD_ILI9341_H__
|
||||
|
||||
#include "ui.hpp"
|
||||
#include "ui_text.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
|
||||
namespace lcd {
|
||||
|
||||
class ILI9341 {
|
||||
public:
|
||||
constexpr ILI9341(
|
||||
) : scroll_state { 0, 0, 320, 0 }
|
||||
{
|
||||
}
|
||||
|
||||
ILI9341(const ILI9341&) = delete;
|
||||
ILI9341(ILI9341&&) = delete;
|
||||
void operator=(const ILI9341&) = delete;
|
||||
|
||||
void init();
|
||||
|
||||
void fill_rectangle(ui::Rect r, const ui::Color c);
|
||||
void fill_circle(
|
||||
const ui::Point center,
|
||||
const ui::Dim radius,
|
||||
const ui::Color foreground,
|
||||
const ui::Color background
|
||||
);
|
||||
|
||||
void draw_pixel(const ui::Point p, const ui::Color color);
|
||||
|
||||
template<size_t N>
|
||||
void draw_pixels(
|
||||
const ui::Rect r,
|
||||
const std::array<ui::Color, N>& colors
|
||||
) {
|
||||
draw_pixels(r, colors.data(), colors.size());
|
||||
}
|
||||
|
||||
void draw_glyph(
|
||||
const ui::Point p,
|
||||
const ui::Glyph& glyph,
|
||||
const ui::Color foreground,
|
||||
const ui::Color background
|
||||
);
|
||||
|
||||
void scroll_set_area(const ui::Coord top_y, const ui::Coord bottom_y);
|
||||
ui::Coord scroll_set_position(const ui::Coord position);
|
||||
ui::Coord scroll(const int32_t delta);
|
||||
ui::Coord scroll_area_y(const ui::Coord y) const;
|
||||
void scroll_disable();
|
||||
|
||||
constexpr ui::Dim width() const { return 240; }
|
||||
constexpr ui::Dim height() const { return 320; }
|
||||
constexpr ui::Rect screen_rect() const { return { 0, 0, width(), height() }; }
|
||||
|
||||
private:
|
||||
struct scroll_t {
|
||||
uint16_t top_area;
|
||||
uint16_t bottom_area;
|
||||
uint16_t height;
|
||||
uint16_t current_position;
|
||||
};
|
||||
|
||||
scroll_t scroll_state;
|
||||
|
||||
void draw_pixels(const ui::Rect r, const ui::Color* const colors, const size_t count);
|
||||
};
|
||||
|
||||
} /* namespace lcd */
|
||||
|
||||
#endif/*__LCD_ILI9341_H__*/
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __LED_H__
|
||||
#define __LED_H__
|
||||
|
||||
#include "gpio.hpp"
|
||||
|
||||
struct LED {
|
||||
constexpr LED(const GPIO gpio) :
|
||||
_gpio { gpio } {
|
||||
}
|
||||
|
||||
void setup() const {
|
||||
_gpio.clear();
|
||||
_gpio.output();
|
||||
_gpio.configure();
|
||||
}
|
||||
|
||||
void on() const {
|
||||
_gpio.set();
|
||||
}
|
||||
|
||||
void off() const {
|
||||
_gpio.clear();
|
||||
}
|
||||
|
||||
void toggle() const {
|
||||
_gpio.toggle();
|
||||
}
|
||||
|
||||
void write(const bool value) const {
|
||||
_gpio.write(value);
|
||||
}
|
||||
|
||||
private:
|
||||
const GPIO _gpio;
|
||||
};
|
||||
|
||||
#endif/*__LED_H__*/
|
||||
@@ -0,0 +1,531 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __LPC43XX_CPP_H__
|
||||
#define __LPC43XX_CPP_H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <hal.h>
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace lpc43xx {
|
||||
|
||||
namespace creg {
|
||||
|
||||
static_assert(offsetof(LPC_CREG_Type, CREG0) == 0x004, "CREG0 offset wrong");
|
||||
static_assert(offsetof(LPC_CREG_Type, M4MEMMAP) == 0x100, "M4MEMMAP offset wrong");
|
||||
static_assert(offsetof(LPC_CREG_Type, CREG5) == 0x118, "CREG5 offset wrong");
|
||||
static_assert(offsetof(LPC_CREG_Type, CHIPID) == 0x200, "CHIPID offset wrong");
|
||||
static_assert(offsetof(LPC_CREG_Type, M0SUBMEMMAP) == 0x308, "M0SUBMEMMAP offset wrong");
|
||||
static_assert(offsetof(LPC_CREG_Type, M0APPTXEVENT) == 0x400, "M0APPTXEVENT offset wrong");
|
||||
static_assert(offsetof(LPC_CREG_Type, USB0FLADJ) == 0x500, "USB0FLADJ offset wrong");
|
||||
static_assert(offsetof(LPC_CREG_Type, USB1FLADJ) == 0x600, "USB1FLADJ offset wrong");
|
||||
|
||||
namespace m4txevent {
|
||||
|
||||
#if defined(LPC43XX_M4)
|
||||
inline void assert() {
|
||||
__SEV();
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void clear() {
|
||||
LPC_CREG->M4TXEVENT = 0;
|
||||
}
|
||||
|
||||
} /* namespace m4txevent */
|
||||
|
||||
namespace m0apptxevent {
|
||||
|
||||
#if defined(LPC43XX_M0)
|
||||
inline void assert() {
|
||||
__SEV();
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void clear() {
|
||||
LPC_CREG->M0APPTXEVENT = 0;
|
||||
}
|
||||
|
||||
} /* namespace */
|
||||
|
||||
} /* namespace creg */
|
||||
|
||||
namespace cgu {
|
||||
|
||||
enum class CLK_SEL {
|
||||
RTC_32KHZ = 0x00,
|
||||
IRC = 0x01,
|
||||
ENET_RX_CLK = 0x02,
|
||||
ENET_TX_CLK = 0x03,
|
||||
GP_CLKIN = 0x04,
|
||||
XTAL = 0x06,
|
||||
PLL0USB = 0x07,
|
||||
PLL0AUDIO = 0x08,
|
||||
PLL1 = 0x09,
|
||||
IDIVA = 0x0c,
|
||||
IDIVB = 0x0d,
|
||||
IDIVC = 0x0e,
|
||||
IDIVD = 0x0f,
|
||||
IDIVE = 0x10,
|
||||
};
|
||||
|
||||
struct IDIV_CTRL {
|
||||
uint32_t pd;
|
||||
uint32_t idiv;
|
||||
uint32_t autoblock;
|
||||
CLK_SEL clk_sel;
|
||||
|
||||
constexpr operator uint32_t() const {
|
||||
return
|
||||
((pd & 1) << 0)
|
||||
| ((idiv & 3) << 2)
|
||||
| ((autoblock & 1) << 11)
|
||||
| ((toUType(clk_sel) & 0x1f) << 24)
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
namespace pll0audio {
|
||||
|
||||
struct CTRL {
|
||||
uint32_t pd;
|
||||
uint32_t bypass;
|
||||
uint32_t directi;
|
||||
uint32_t directo;
|
||||
uint32_t clken;
|
||||
uint32_t frm;
|
||||
uint32_t autoblock;
|
||||
uint32_t pllfract_req;
|
||||
uint32_t sel_ext;
|
||||
uint32_t mod_pd;
|
||||
CLK_SEL clk_sel;
|
||||
|
||||
constexpr operator uint32_t() const {
|
||||
return
|
||||
((pd & 1) << 0)
|
||||
| ((bypass & 1) << 1)
|
||||
| ((directi & 1) << 2)
|
||||
| ((directo & 1) << 3)
|
||||
| ((clken & 1) << 4)
|
||||
| ((frm & 1) << 6)
|
||||
| ((autoblock & 1) << 11)
|
||||
| ((pllfract_req & 1) << 12)
|
||||
| ((sel_ext & 1) << 13)
|
||||
| ((mod_pd & 1) << 14)
|
||||
| ((toUType(clk_sel) & 0x1f) << 24)
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
struct MDIV {
|
||||
uint32_t mdec;
|
||||
|
||||
constexpr operator uint32_t() const {
|
||||
return ((mdec & 0x1ffff) << 0);
|
||||
}
|
||||
};
|
||||
|
||||
struct NP_DIV {
|
||||
uint32_t pdec;
|
||||
uint32_t ndec;
|
||||
|
||||
constexpr operator uint32_t() const {
|
||||
return
|
||||
((pdec & 0x7f) << 0)
|
||||
| ((ndec & 0x3ff) << 12)
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
struct FRAC {
|
||||
uint32_t pllfract_ctrl;
|
||||
|
||||
constexpr operator uint32_t() const {
|
||||
return ((pllfract_ctrl & 0x3fffff) << 0);
|
||||
}
|
||||
};
|
||||
|
||||
inline void ctrl(const CTRL& value) {
|
||||
LPC_CGU->PLL0AUDIO_CTRL = value;
|
||||
}
|
||||
|
||||
inline void mdiv(const MDIV& value) {
|
||||
LPC_CGU->PLL0AUDIO_MDIV = value;
|
||||
}
|
||||
|
||||
inline void np_div(const NP_DIV& value) {
|
||||
LPC_CGU->PLL0AUDIO_NP_DIV = value;
|
||||
}
|
||||
|
||||
inline void frac(const FRAC& value) {
|
||||
LPC_CGU->PLL0AUDIO_FRAC = value;
|
||||
}
|
||||
|
||||
inline void power_up() {
|
||||
LPC_CGU->PLL0AUDIO_CTRL &= ~(1U << 0);
|
||||
}
|
||||
|
||||
inline void power_down() {
|
||||
LPC_CGU->PLL0AUDIO_CTRL |= (1U << 0);
|
||||
}
|
||||
|
||||
inline bool is_locked() {
|
||||
return LPC_CGU->PLL0AUDIO_STAT & (1U << 0);
|
||||
}
|
||||
|
||||
inline void clock_enable() {
|
||||
LPC_CGU->PLL0AUDIO_CTRL |= (1U << 4);
|
||||
}
|
||||
|
||||
inline void clock_disable() {
|
||||
LPC_CGU->PLL0AUDIO_CTRL &= ~(1U << 4);
|
||||
}
|
||||
|
||||
} /* namespace pll0audio */
|
||||
|
||||
namespace pll1 {
|
||||
|
||||
struct CTRL {
|
||||
uint32_t pd;
|
||||
uint32_t bypass;
|
||||
uint32_t fbsel;
|
||||
uint32_t direct;
|
||||
uint32_t psel;
|
||||
uint32_t autoblock;
|
||||
uint32_t nsel;
|
||||
uint32_t msel;
|
||||
CLK_SEL clk_sel;
|
||||
|
||||
constexpr operator uint32_t() const {
|
||||
return
|
||||
((pd & 1) << 0)
|
||||
| ((bypass & 1) << 1)
|
||||
| ((fbsel & 1) << 6)
|
||||
| ((direct & 1) << 7)
|
||||
| ((psel & 3) << 8)
|
||||
| ((autoblock & 1) << 11)
|
||||
| ((nsel & 3) << 12)
|
||||
| ((msel & 0xff) << 16)
|
||||
| ((toUType(clk_sel) & 0x1f) << 24)
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
inline void ctrl(const CTRL& value) {
|
||||
LPC_CGU->PLL1_CTRL = value;
|
||||
}
|
||||
|
||||
inline void enable() {
|
||||
LPC_CGU->PLL1_CTRL &= ~(1U << 0);
|
||||
}
|
||||
|
||||
inline void disable() {
|
||||
LPC_CGU->PLL1_CTRL |= (1U << 0);
|
||||
}
|
||||
|
||||
inline void direct() {
|
||||
LPC_CGU->PLL1_CTRL |= (1U << 7);
|
||||
}
|
||||
|
||||
inline bool is_locked() {
|
||||
return LPC_CGU->PLL1_STAT & (1U << 0);
|
||||
}
|
||||
|
||||
} /* namespace pll1 */
|
||||
|
||||
} /* namespace cgu */
|
||||
|
||||
namespace ccu1 {
|
||||
|
||||
static_assert(offsetof(LPC_CCU1_Type, CLK_ADCHS_STAT) == 0xb04, "CLK_ADCHS_STAT offset wrong");
|
||||
|
||||
} /* namespace ccu1 */
|
||||
|
||||
namespace rgu {
|
||||
|
||||
enum class Reset {
|
||||
CORE = 0,
|
||||
PERIPH = 1,
|
||||
MASTER = 2,
|
||||
WWDT = 4,
|
||||
CREG = 5,
|
||||
BUS = 8,
|
||||
SCU = 9,
|
||||
M0_SUB = 12,
|
||||
M4_RST = 13,
|
||||
LCD = 16,
|
||||
USB0 = 17,
|
||||
USB1 = 18,
|
||||
DMA = 19,
|
||||
SDIO = 20,
|
||||
EMC = 21,
|
||||
ETHERNET = 22,
|
||||
FLASHA = 25,
|
||||
EEPROM = 27,
|
||||
GPIO = 28,
|
||||
FLASHB = 29,
|
||||
TIMER0 = 32,
|
||||
TIMER1 = 33,
|
||||
TIMER2 = 34,
|
||||
TIMER3 = 35,
|
||||
RITIMER = 36,
|
||||
SCT = 37,
|
||||
MOTOCONPWM = 38,
|
||||
QEI = 39,
|
||||
ADC0 = 40,
|
||||
ADC1 = 41,
|
||||
DAC = 42,
|
||||
UART0 = 44,
|
||||
UART1 = 45,
|
||||
UART2 = 46,
|
||||
UART3 = 47,
|
||||
I2C0 = 48,
|
||||
I2C1 = 49,
|
||||
SSP0 = 50,
|
||||
SSP1 = 51,
|
||||
I2S = 52,
|
||||
SPIFI = 53,
|
||||
CAN1 = 54,
|
||||
CAN0 = 55,
|
||||
M0APP = 56,
|
||||
SGPIO = 57,
|
||||
SPI = 58,
|
||||
ADCHS = 60,
|
||||
};
|
||||
|
||||
enum class Status {
|
||||
NotActive = 0b00,
|
||||
ActivatedByRGUInput = 0b01,
|
||||
ActivatedBySoftware = 0b11,
|
||||
};
|
||||
|
||||
inline void reset(const Reset reset) {
|
||||
LPC_RGU->RESET_CTRL[toUType(reset) >> 5] |= (1U << (toUType(reset) & 0x1f));
|
||||
}
|
||||
|
||||
inline void reset_mask(const uint64_t mask) {
|
||||
LPC_RGU->RESET_CTRL[0] = mask & 0xffffffffU;
|
||||
LPC_RGU->RESET_CTRL[1] = mask >> 32;
|
||||
}
|
||||
|
||||
inline Status status(const Reset reset) {
|
||||
return static_cast<Status>(
|
||||
(LPC_RGU->RESET_STATUS[toUType(reset) >> 4] >> ((toUType(reset) & 0xf) * 2)) & 3
|
||||
);
|
||||
}
|
||||
|
||||
inline bool active(const Reset reset) {
|
||||
return (LPC_RGU->RESET_ACTIVE_STATUS[toUType(reset) >> 5] >> (toUType(reset) & 0x1f)) & 1;
|
||||
}
|
||||
|
||||
inline uint32_t external_status(const Reset reset) {
|
||||
return LPC_RGU->RESET_EXT_STAT[toUType(reset)];
|
||||
}
|
||||
|
||||
inline uint64_t operator|(Reset r1, Reset r2) {
|
||||
return (1ULL << toUType(r1)) | (1ULL << toUType(r2));
|
||||
}
|
||||
|
||||
inline uint64_t operator|(uint64_t m, Reset r) {
|
||||
return m | (1ULL << toUType(r));
|
||||
}
|
||||
|
||||
static_assert(offsetof(LPC_RGU_Type, RESET_CTRL[0]) == 0x100, "RESET_CTRL[0] offset wrong");
|
||||
static_assert(offsetof(LPC_RGU_Type, RESET_STATUS[0]) == 0x110, "RESET_STATUS[0] offset wrong");
|
||||
static_assert(offsetof(LPC_RGU_Type, RESET_ACTIVE_STATUS[0]) == 0x150, "RESET_ACTIVE_STATUS[0] offset wrong");
|
||||
static_assert(offsetof(LPC_RGU_Type, RESET_EXT_STAT[1]) == 0x404, "RESET_EXT_STAT[1] offset wrong");
|
||||
static_assert(offsetof(LPC_RGU_Type, RESET_EXT_STAT[60]) == 0x4f0, "RESET_EXT_STAT[60] offset wrong");
|
||||
|
||||
} /* namespace rgu */
|
||||
|
||||
namespace scu {
|
||||
|
||||
struct SFS {
|
||||
uint32_t mode;
|
||||
uint32_t epd;
|
||||
uint32_t epun;
|
||||
uint32_t ehs;
|
||||
uint32_t ezi;
|
||||
uint32_t zif;
|
||||
|
||||
constexpr operator uint32_t() const {
|
||||
return
|
||||
((mode & 7) << 0)
|
||||
| ((epd & 1) << 3)
|
||||
| ((epun & 1) << 4)
|
||||
| ((ehs & 1) << 5)
|
||||
| ((ezi & 1) << 6)
|
||||
| ((zif & 1) << 7)
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(offsetof(LPC_SCU_Type, PINTSEL0) == 0xe00, "PINTSEL0 offset wrong");
|
||||
|
||||
} /* namespace scu */
|
||||
|
||||
namespace sgpio {
|
||||
|
||||
static_assert(offsetof(LPC_SGPIO_Type, MASK_A) == 0x0200, "SGPIO MASK_A offset wrong");
|
||||
static_assert(offsetof(LPC_SGPIO_Type, GPIO_OUTREG) == 0x0214, "SGPIO GPIO_OUTREG offset wrong");
|
||||
static_assert(offsetof(LPC_SGPIO_Type, CTRL_DISABLE) == 0x0220, "SGPIO CTRL_DISABLE offset wrong");
|
||||
static_assert(offsetof(LPC_SGPIO_Type, CLR_EN_0) == 0x0f00, "SGPIO CLR_EN_0 offset wrong");
|
||||
static_assert(offsetof(LPC_SGPIO_Type, CLR_EN_1) == 0x0f20, "SGPIO CLR_EN_1 offset wrong");
|
||||
static_assert(offsetof(LPC_SGPIO_Type, CLR_EN_2) == 0x0f40, "SGPIO CLR_EN_2 offset wrong");
|
||||
static_assert(offsetof(LPC_SGPIO_Type, CLR_EN_3) == 0x0f60, "SGPIO CLR_EN_3 offset wrong");
|
||||
static_assert(offsetof(LPC_SGPIO_Type, SET_STATUS_3) == 0x0f74, "SGPIO SET_STATUS_3 offset wrong");
|
||||
static_assert(sizeof(LPC_SGPIO_Type) == 0x0f78, "SGPIO type size wrong");
|
||||
|
||||
} /* namespace sgpio */
|
||||
|
||||
namespace gpdma {
|
||||
|
||||
static_assert(offsetof(LPC_GPDMA_Type, SYNC) == 0x034, "GPDMA SYNC offset wrong");
|
||||
static_assert(offsetof(LPC_GPDMA_Type, CH[0]) == 0x100, "GPDMA CH[0] offset wrong");
|
||||
static_assert(offsetof(LPC_GPDMA_Type, CH[7]) == 0x1e0, "GPDMA CH[7] offset wrong");
|
||||
|
||||
} /* namespace gpdma */
|
||||
|
||||
namespace sdmmc {
|
||||
|
||||
static_assert(offsetof(LPC_SDMMC_Type, RESP0) == 0x030, "SDMMC RESP0 offset wrong");
|
||||
static_assert(offsetof(LPC_SDMMC_Type, TCBCNT) == 0x05c, "SDMMC TCBCNT offset wrong");
|
||||
static_assert(offsetof(LPC_SDMMC_Type, RST_N) == 0x078, "SDMMC RST_N offset wrong");
|
||||
static_assert(offsetof(LPC_SDMMC_Type, BMOD) == 0x080, "SDMMC BMOD offset wrong");
|
||||
static_assert(offsetof(LPC_SDMMC_Type, DATA) == 0x100, "SDMMC DATA offset wrong");
|
||||
|
||||
} /* namespace sdmmc */
|
||||
|
||||
namespace spifi {
|
||||
|
||||
struct CTRL {
|
||||
uint32_t timeout;
|
||||
uint32_t cshigh;
|
||||
uint32_t d_prftch_dis;
|
||||
uint32_t inten;
|
||||
uint32_t mode3;
|
||||
uint32_t prftch_dis;
|
||||
uint32_t dual;
|
||||
uint32_t rfclk;
|
||||
uint32_t fbclk;
|
||||
uint32_t dmaen;
|
||||
|
||||
constexpr operator uint32_t() const {
|
||||
return
|
||||
((timeout & 0xffff) << 0)
|
||||
| ((cshigh & 1) << 16)
|
||||
| ((d_prftch_dis & 1) << 21)
|
||||
| ((inten & 1) << 22)
|
||||
| ((mode3 & 1) << 23)
|
||||
| ((prftch_dis & 1) << 27)
|
||||
| ((dual & 1) << 28)
|
||||
| ((rfclk & 1) << 29)
|
||||
| ((fbclk & 1) << 30)
|
||||
| ((dmaen & 1) << 31)
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(offsetof(LPC_SPIFI_Type, STAT) == 0x01c, "SPIFI STAT offset wrong");
|
||||
|
||||
} /* namespace spifi */
|
||||
|
||||
namespace timer {
|
||||
|
||||
static_assert(offsetof(LPC_TIMER_Type, MR[0]) == 0x018, "TIMER MR[0] offset wrong");
|
||||
static_assert(offsetof(LPC_TIMER_Type, CCR) == 0x028, "TIMER CCR offset wrong");
|
||||
static_assert(offsetof(LPC_TIMER_Type, EMR) == 0x03c, "TIMER EMR offset wrong");
|
||||
static_assert(offsetof(LPC_TIMER_Type, CTCR) == 0x070, "TIMER CTCR offset wrong");
|
||||
|
||||
} /* namespace timer */
|
||||
|
||||
namespace rtc {
|
||||
|
||||
namespace interrupt {
|
||||
|
||||
inline void clear_all() {
|
||||
LPC_RTC->ILR = (1U << 1) | (1U << 0);
|
||||
}
|
||||
|
||||
inline void enable_second_inc() {
|
||||
LPC_RTC->CIIR = (1U << 0);
|
||||
}
|
||||
|
||||
} /* namespace */
|
||||
|
||||
#if HAL_USE_RTC
|
||||
struct RTC : public RTCTime {
|
||||
constexpr RTC(
|
||||
uint32_t year,
|
||||
uint32_t month,
|
||||
uint32_t day,
|
||||
uint32_t hour,
|
||||
uint32_t minute,
|
||||
uint32_t second
|
||||
) : RTCTime {
|
||||
(year << 16) | (month << 8) | (day << 0),
|
||||
(hour << 16) | (minute << 8) | (second << 0)
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
constexpr RTC(
|
||||
) : RTCTime { 0, 0 }
|
||||
{
|
||||
}
|
||||
|
||||
uint16_t year() const {
|
||||
return (tv_date >> 16) & 0xfff;
|
||||
}
|
||||
|
||||
uint8_t month() const {
|
||||
return (tv_date >> 8) & 0x00f;
|
||||
}
|
||||
|
||||
uint8_t day() const {
|
||||
return (tv_date >> 0) & 0x01f;
|
||||
}
|
||||
|
||||
uint8_t hour() const {
|
||||
return (tv_time >> 16) & 0x01f;
|
||||
}
|
||||
|
||||
uint8_t minute() const {
|
||||
return (tv_time >> 8) & 0x03f;
|
||||
}
|
||||
|
||||
uint8_t second() const {
|
||||
return (tv_time >> 0) & 0x03f;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
static_assert(offsetof(LPC_RTC_Type, CCR) == 0x008, "RTC CCR offset wrong");
|
||||
static_assert(offsetof(LPC_RTC_Type, ASEC) == 0x060, "RTC ASEC offset wrong");
|
||||
|
||||
} /* namespace rtc */
|
||||
|
||||
} /* namespace lpc43xx */
|
||||
|
||||
#endif/*__LPC43XX_CPP_H__*/
|
||||
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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 __MESSAGE_H__
|
||||
#define __MESSAGE_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <array>
|
||||
#include <functional>
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
class Message {
|
||||
public:
|
||||
enum class ID : uint16_t {
|
||||
/* Assign consecutive IDs. IDs are used to index array. */
|
||||
RSSIStatistics = 0,
|
||||
BasebandStatistics = 1,
|
||||
ChannelStatistics = 2,
|
||||
ChannelSpectrum = 3,
|
||||
AudioStatistics = 4,
|
||||
BasebandConfiguration = 5,
|
||||
FSKConfiguration = 6,
|
||||
FSKPacket = 7,
|
||||
TestResults = 8,
|
||||
MAX
|
||||
};
|
||||
|
||||
constexpr Message(
|
||||
ID id
|
||||
) : id { id },
|
||||
state { State::Free }
|
||||
{
|
||||
}
|
||||
|
||||
enum class State : uint16_t {
|
||||
Free,
|
||||
InUse,
|
||||
};
|
||||
|
||||
bool is_free() const {
|
||||
return state == State::Free;
|
||||
}
|
||||
|
||||
const ID id;
|
||||
volatile State state;
|
||||
};
|
||||
|
||||
struct RSSIStatistics {
|
||||
uint32_t accumulator { 0 };
|
||||
uint32_t min { 0 };
|
||||
uint32_t max { 0 };
|
||||
uint32_t count { 0 };
|
||||
};
|
||||
|
||||
class RSSIStatisticsMessage : public Message {
|
||||
public:
|
||||
constexpr RSSIStatisticsMessage(
|
||||
) : Message { ID::RSSIStatistics },
|
||||
statistics { }
|
||||
{
|
||||
}
|
||||
|
||||
RSSIStatistics statistics;
|
||||
};
|
||||
|
||||
struct BasebandStatistics {
|
||||
uint32_t idle_ticks { 0 };
|
||||
uint32_t baseband_ticks { 0 };
|
||||
bool saturation { false };
|
||||
};
|
||||
|
||||
class BasebandStatisticsMessage : public Message {
|
||||
public:
|
||||
constexpr BasebandStatisticsMessage(
|
||||
) : Message { ID::BasebandStatistics },
|
||||
statistics { }
|
||||
{
|
||||
}
|
||||
|
||||
BasebandStatistics statistics;
|
||||
};
|
||||
|
||||
struct ChannelStatistics {
|
||||
int32_t max_db;
|
||||
size_t count;
|
||||
|
||||
constexpr ChannelStatistics(
|
||||
) : max_db { -120 },
|
||||
count { 0 }
|
||||
{
|
||||
}
|
||||
|
||||
constexpr ChannelStatistics(
|
||||
int32_t max_db,
|
||||
size_t count
|
||||
) : max_db { max_db },
|
||||
count { count }
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class ChannelStatisticsMessage : public Message {
|
||||
public:
|
||||
constexpr ChannelStatisticsMessage(
|
||||
) : Message { ID::ChannelStatistics },
|
||||
statistics { }
|
||||
{
|
||||
}
|
||||
|
||||
ChannelStatistics statistics;
|
||||
};
|
||||
|
||||
struct AudioStatistics {
|
||||
int32_t rms_db;
|
||||
int32_t max_db;
|
||||
size_t count;
|
||||
|
||||
constexpr AudioStatistics(
|
||||
) : rms_db { -120 },
|
||||
max_db { -120 },
|
||||
count { 0 }
|
||||
{
|
||||
}
|
||||
|
||||
constexpr AudioStatistics(
|
||||
int32_t rms_db,
|
||||
int32_t max_db,
|
||||
size_t count
|
||||
) : rms_db { rms_db },
|
||||
max_db { max_db },
|
||||
count { count }
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class AudioStatisticsMessage : public Message {
|
||||
public:
|
||||
constexpr AudioStatisticsMessage(
|
||||
) : Message { ID::AudioStatistics },
|
||||
statistics { }
|
||||
{
|
||||
}
|
||||
|
||||
AudioStatistics statistics;
|
||||
};
|
||||
|
||||
struct BasebandConfiguration {
|
||||
int32_t mode;
|
||||
uint32_t sampling_rate;
|
||||
size_t decimation_factor;
|
||||
};
|
||||
|
||||
class BasebandConfigurationMessage : public Message {
|
||||
public:
|
||||
constexpr BasebandConfigurationMessage(
|
||||
BasebandConfiguration configuration
|
||||
) : Message { ID::BasebandConfiguration },
|
||||
configuration(configuration)
|
||||
{
|
||||
}
|
||||
|
||||
BasebandConfiguration configuration;
|
||||
};
|
||||
|
||||
struct ChannelSpectrum {
|
||||
std::array<uint8_t, 256>* db { nullptr };
|
||||
size_t db_count { 256 };
|
||||
uint32_t bandwidth { 0 };
|
||||
};
|
||||
|
||||
class ChannelSpectrumMessage : public Message {
|
||||
public:
|
||||
constexpr ChannelSpectrumMessage(
|
||||
) : Message { ID::ChannelSpectrum }
|
||||
{
|
||||
}
|
||||
|
||||
ChannelSpectrum spectrum;
|
||||
};
|
||||
|
||||
struct FSKConfiguration {
|
||||
uint32_t symbol_rate;
|
||||
uint32_t access_code;
|
||||
size_t access_code_length;
|
||||
size_t access_code_tolerance;
|
||||
size_t packet_length;
|
||||
};
|
||||
|
||||
class FSKConfigurationMessage : public Message {
|
||||
public:
|
||||
constexpr FSKConfigurationMessage(
|
||||
FSKConfiguration configuration
|
||||
) : Message { ID::FSKConfiguration },
|
||||
configuration(configuration)
|
||||
{
|
||||
}
|
||||
|
||||
FSKConfiguration configuration;
|
||||
};
|
||||
|
||||
#include <bitset>
|
||||
|
||||
struct FSKPacket {
|
||||
std::bitset<256> payload;
|
||||
size_t bits_received;
|
||||
|
||||
FSKPacket(
|
||||
) : bits_received { 0 }
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class FSKPacketMessage : public Message {
|
||||
public:
|
||||
FSKPacketMessage(
|
||||
) : Message { ID::FSKPacket }
|
||||
{
|
||||
}
|
||||
|
||||
FSKPacket packet;
|
||||
};
|
||||
|
||||
class MessageHandlerMap {
|
||||
public:
|
||||
using MessageHandler = std::function<void(const Message* const p)>;
|
||||
|
||||
MessageHandler& operator[](Message::ID n) {
|
||||
return map_[toUType(n)];
|
||||
}
|
||||
|
||||
const MessageHandler& operator[](Message::ID n) const {
|
||||
return map_[toUType(n)];
|
||||
}
|
||||
|
||||
private:
|
||||
using MapType = std::array<MessageHandler, toUType(Message::ID::MAX)>;
|
||||
MapType map_;
|
||||
};
|
||||
|
||||
#endif/*__MESSAGE_H__*/
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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 "message_queue.hpp"
|
||||
|
||||
#include "ch.h"
|
||||
#include "lpc43xx_cpp.hpp"
|
||||
|
||||
using namespace lpc43xx;
|
||||
|
||||
bool MessageQueue::push(Message* const message) {
|
||||
/* Returns true if success:
|
||||
* - Message not in use.
|
||||
* - FIFO wasn't full.
|
||||
*/
|
||||
if( message->state == Message::State::Free ) {
|
||||
message->state = Message::State::InUse;
|
||||
|
||||
if( enqueue(message) ) {
|
||||
signal();
|
||||
return true;
|
||||
} else {
|
||||
// Roll back message state.
|
||||
message->state = Message::State::Free;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Message* MessageQueue::pop() {
|
||||
/* TODO: Because of architecture characteristics, the two LSBs of the
|
||||
* message pointer will always be 0. Other (non-pointer) message types
|
||||
* could be encoded by setting these two bits to non-zero values.
|
||||
* One of the bits could also be used as an "ack" flag... In fact, a
|
||||
* pointer message could be turned into an "ack" message, or something
|
||||
* like that...
|
||||
* Might be better though to use formal operating structures in the
|
||||
* message to do synchronization between processors.
|
||||
*/
|
||||
Message* message { nullptr };
|
||||
const auto success = fifo.out(&message, 1);
|
||||
return success ? message : nullptr;
|
||||
}
|
||||
|
||||
#if defined(LPC43XX_M0)
|
||||
bool MessageQueue::enqueue(Message* const message) {
|
||||
return fifo.in(&message, 1);
|
||||
}
|
||||
|
||||
void MessageQueue::signal() {
|
||||
creg::m0apptxevent::assert();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(LPC43XX_M4)
|
||||
bool MessageQueue::enqueue(Message* const message) {
|
||||
return fifo.in(&message, 1);
|
||||
}
|
||||
|
||||
void MessageQueue::signal() {
|
||||
creg::m4txevent::assert();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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 __MESSAGE_QUEUE_H__
|
||||
#define __MESSAGE_QUEUE_H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "message.hpp"
|
||||
#include "fifo.hpp"
|
||||
|
||||
class MessageQueue {
|
||||
public:
|
||||
bool push(Message* const message);
|
||||
|
||||
Message* pop();
|
||||
|
||||
size_t len() const {
|
||||
return fifo.len();
|
||||
}
|
||||
|
||||
bool is_empty() const {
|
||||
return fifo.is_empty();
|
||||
}
|
||||
|
||||
private:
|
||||
FIFO<Message*, 8> fifo;
|
||||
|
||||
bool enqueue(Message* const message);
|
||||
void signal();
|
||||
};
|
||||
|
||||
#endif/*__MESSAGE_QUEUE_H__*/
|
||||
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __PINS_H__
|
||||
#define __PINS_H__
|
||||
|
||||
#include "gpio.hpp"
|
||||
|
||||
namespace lpc43xx {
|
||||
|
||||
enum Pins {
|
||||
P0_0, P0_1,
|
||||
P1_0, P1_1, P1_2, P1_3, P1_4, P1_5, P1_6, P1_7, P1_8, P1_9, P1_10, P1_11, P1_12, P1_13, P1_14, P1_15, P1_16, P1_17, P1_18, P1_19, P1_20,
|
||||
P2_0, P2_1, P2_2, P2_3, P2_4, P2_5, P2_6, P2_7, P2_8, P2_9, P2_10, P2_11, P2_12, P2_13,
|
||||
P3_0, P3_1, P3_2, /*P3_3, P3_4, P3_5, P3_6, P3_7, P3_8,*/
|
||||
P4_0, P4_1, P4_2, P4_3, P4_4, P4_5, P4_6, P4_7, P4_8, P4_9, P4_10,
|
||||
P5_0, P5_1, P5_2, P5_3, P5_4, P5_5, P5_6, P5_7,
|
||||
P6_0, P6_1, P6_2, P6_3, P6_4, P6_5, P6_6, P6_7, P6_8, P6_9, P6_10, P6_11, P6_12,
|
||||
P7_0, P7_1, P7_2, P7_3, P7_4, P7_5, P7_6, P7_7,
|
||||
P9_5, P9_6,
|
||||
PF_4,
|
||||
CLK0, CLK2,
|
||||
};
|
||||
|
||||
constexpr Pin pins[] = {
|
||||
[P0_0] = { 0, 0, PinConfig::sgpio_inout_fast(3) }, /* SGPIO0/P75/BANK2F3M3: CPLD.89/HOST_DATA0(IO) */
|
||||
[P0_1] = { 0, 1, PinConfig::sgpio_inout_fast(3) }, /* SGPIO1/BANK2F3M5: CPLD.79/HOST_DATA1(IO) */
|
||||
[P1_0] = { 1, 0, PinConfig::sgpio_inout_fast(6) }, /* SGPIO7/P76/BANK2F3M7: CPLD.77/HOST_DATA7(IO) */
|
||||
[P1_1] = { 1, 1, { .mode=0, .pd=0, .pu=0, .fast=0, .input=1, .ifilt=1 } }, /* P1_1/P74: 10K PU, BOOT0 */
|
||||
[P1_2] = { 1, 2, { .mode=0, .pd=0, .pu=0, .fast=0, .input=1, .ifilt=1 } }, /* P1_2/P73: 10K PD, BOOT1 */
|
||||
[P1_3] = { 1, 3, { .mode=5, .pd=0, .pu=0, .fast=0, .input=1, .ifilt=1 } }, /* SSP1_MISO/P41: MAX2837.DOUT(O) */
|
||||
[P1_4] = { 1, 4, { .mode=5, .pd=1, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* SSP1_MOSI/P40: MAX2837.DIN(I), MAX5864.DIN(I) */
|
||||
[P1_5] = { 1, 5, { .mode=0, .pd=0, .pu=1, .fast=0, .input=1, .ifilt=1 } }, /* SD_POW: PortaPack CPLD.TDO(O) */
|
||||
[P1_6] = { 1, 6, { .mode=7, .pd=0, .pu=1, .fast=1, .input=1, .ifilt=0 } }, /* SD_CMD: PortaPack SD.CMD(IO) */
|
||||
[P1_7] = { 1, 7, { .mode=0, .pd=1, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* !MIX_BYPASS/P35: U1.VCTL1(I), U11.VCTL2(I), U9.V2(I) */
|
||||
[P1_8] = { 1, 8, { .mode=0, .pd=0, .pu=1, .fast=0, .input=0, .ifilt=1 } }, /* SD_VOLT0: PortaPack CPLD.TMS(I) */
|
||||
[P1_9] = { 1, 9, { .mode=7, .pd=0, .pu=1, .fast=1, .input=1, .ifilt=0 } }, /* SD_DAT0: PortaPack SD.DAT0(IO) */
|
||||
[P1_10] = { 1, 10, { .mode=7, .pd=0, .pu=1, .fast=1, .input=1, .ifilt=0 } }, /* SD_DAT1: PortaPack SD.DAT1(IO) */
|
||||
[P1_11] = { 1, 11, { .mode=7, .pd=0, .pu=1, .fast=1, .input=1, .ifilt=0 } }, /* SD_DAT2: PortaPack SD.DAT2(IO) */
|
||||
[P1_12] = { 1, 12, { .mode=7, .pd=0, .pu=1, .fast=1, .input=1, .ifilt=0 } }, /* SD_DAT3: PortaPack SD.DAT3(IO) */
|
||||
[P1_13] = { 1, 13, { .mode=7, .pd=0, .pu=1, .fast=0, .input=1, .ifilt=1 } }, /* SD_CD: PortaPack SD.CD(O) */
|
||||
[P1_14] = { 1, 14, PinConfig::sgpio_out_fast_with_pullup(6) }, /* SGPIO10/P78/BANK2F3M8: CPLD.76/HOST_DISABLE(I) */
|
||||
[P1_15] = { 1, 15, PinConfig::sgpio_inout_fast(2) }, /* SGPIO2/BANK2F3M9: CPLD.74/HOST_DATA2(IO) */
|
||||
[P1_16] = { 1, 16, PinConfig::sgpio_inout_fast(2) }, /* SGPIO3/BANK2F3M10: CPLD.72/HOST_DATA3(IO) */
|
||||
[P1_17] = { 1, 17, PinConfig::sgpio_out_fast_with_pullup(6) }, /* SGPIO11/P79/BANK2F3M11: CPLD.71/HOST_DIRECTION(I) */
|
||||
[P1_18] = { 1, 18, PinConfig::gpio_out_with_pulldown(0) }, /* SGPIO12/BANK2F3M12: CPLD.70/HOST_Q_INVERT(I) */
|
||||
[P1_19] = { 1, 19, { .mode=1, .pd=1, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* SSP1_SCK/P39: MAX2837.SCLK(I), MAX5864.SCLK(I) */
|
||||
[P1_20] = { 1, 20, { .mode=0, .pd=0, .pu=1, .fast=0, .input=0, .ifilt=1 } }, /* CS_XCVR/P53: MAX2837.CS(I) */
|
||||
[P2_0] = { 2, 0, { .mode=4, .pd=0, .pu=1, .fast=0, .input=1, .ifilt=1 } }, /* U0_TXD: PortaPack P2_0/IO_STBX */
|
||||
[P2_1] = { 2, 1, { .mode=4, .pd=1, .pu=0, .fast=0, .input=1, .ifilt=1 } }, /* U0_RXD: PortaPack P2_1/ADDR */
|
||||
[P2_2] = { 2, 2, PinConfig::sgpio_inout_fast(0) }, /* SGPIO6/BANK2F3M16: CPLD.61/HOST_DATA6(IO) */
|
||||
[P2_3] = { 2, 3, { .mode=4, .pd=0, .pu=0, .fast=0, .input=1, .ifilt=1 } }, /* I2C1_SDA: PortaPack P2_3/LCD_TE */
|
||||
[P2_4] = { 2, 4, { .mode=4, .pd=0, .pu=0, .fast=0, .input=1, .ifilt=1 } }, /* I2C1_SCL: PortaPack P2_4/<unused> */
|
||||
[P2_5] = { 2, 5, { .mode=4, .pd=1, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* RX/P43: U7.VCTL1(I), U10.VCTL1(I), U2.VCTL1(I) */
|
||||
[P2_6] = { 2, 6, { .mode=4, .pd=0, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* MIXER_SCLK/P31: 33pF, RFFC5072.SCLK(I) */
|
||||
[P2_7] = { 2, 7, { .mode=0, .pd=0, .pu=0, .fast=0, .input=1, .ifilt=1 } }, /* ISP: 10K PU, Unused */
|
||||
[P2_8] = { 2, 8, { .mode=4, .pd=0, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* P2_8: 10K PD, BOOT2, DFU switch, PortaPack P2_8/LCD_RD */
|
||||
[P2_9] = { 2, 9, { .mode=0, .pd=0, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* P2_9: 10K PD, BOOT3, PortaPack P2_9/LCD_WR */
|
||||
[P2_10] = { 2, 10, { .mode=0, .pd=0, .pu=1, .fast=0, .input=0, .ifilt=1 } }, /* AMP_BYPASS/P50: U14.V2(I), U12.V2(I) */
|
||||
[P2_11] = { 2, 11, { .mode=0, .pd=1, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* RX_AMP/P49: U12.V1(I), U14.V3(I) */
|
||||
[P2_12] = { 2, 12, { .mode=0, .pd=0, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* !RX_AMP_PWR/P52: 10K PU, Q1.G(I), power to U13 (RX amp) */
|
||||
[P2_13] = { 2, 13, { .mode=0, .pd=0, .pu=1, .fast=0, .input=1, .ifilt=1 } }, /* P2_13: PortaPack P2_13/DIR */
|
||||
[P3_0] = { 3, 0, { .mode=2, .pd=0, .pu=1, .fast=0, .input=0, .ifilt=1 } }, /* I2S0_TX_SCK: PortaPack I2S0_TX_SCK(I) */
|
||||
[P3_1] = { 3, 1, { .mode=0, .pd=0, .pu=1, .fast=0, .input=0, .ifilt=1 } }, /* I2S0_RX_WS: PortaPack I2S0_TX_WS(I) */
|
||||
[P3_2] = { 3, 2, { .mode=0, .pd=0, .pu=1, .fast=0, .input=0, .ifilt=1 } }, /* I2S0_RX_SDA: PortaPack I2S0_TX_SDA(I) */
|
||||
//[P3_3] = { 3, 3, { .mode=3, .pd=1, .pu=0, .fast=1, .input=1, .ifilt=0 } }, /* SPIFI_SCK: W25Q80BV.CLK(I), enable input buffer for timing feedback */
|
||||
//[P3_4] = { 3, 4, { .mode=3, .pd=0, .pu=1, .fast=1, .input=1, .ifilt=0 } }, /* SPIFI_SIO3/P82: W25Q80BV.HOLD(IO) */
|
||||
//[P3_5] = { 3, 5, { .mode=3, .pd=0, .pu=1, .fast=1, .input=1, .ifilt=0 } }, /* SPIFI_SIO2/P81: W25Q80BV.WP(IO) */
|
||||
//[P3_6] = { 3, 6, { .mode=3, .pd=0, .pu=1, .fast=1, .input=1, .ifilt=0 } }, /* SPIFI_MISO: W25Q80BV.DO(IO) */
|
||||
//[P3_7] = { 3, 7, { .mode=3, .pd=0, .pu=1, .fast=1, .input=1, .ifilt=0 } }, /* SPIFI_MOSI: W25Q80BV.DI(IO) */
|
||||
//[P3_8] = { 3, 8, { .mode=3, .pd=0, .pu=1, .fast=1, .input=0, .ifilt=1 } }, /* SPIFI_CS/P68: W25Q80BV.CS(I) */
|
||||
[P4_0] = { 4, 0, { .mode=0, .pd=0, .pu=1, .fast=0, .input=0, .ifilt=1 } }, /* HP/P44: U6.VCTL1(I), U5.VCTL2(I) */
|
||||
[P4_1] = { 4, 1, PinConfig::gpio_led(0) }, /* LED1: LED1.A(I) */
|
||||
[P4_2] = { 4, 2, PinConfig::gpio_led(0) }, /* LED2: LED2.A(I) */
|
||||
[P4_3] = { 4, 3, PinConfig::sgpio_in_fast(7) }, /* SGPIO9/P77/BANK2F3M1: CPLD.91/HOST_CAPTURE(O) */
|
||||
[P4_4] = { 4, 4, { .mode=0, .pd=1, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* TXENABLE/P55: MAX2837.TXENABLE(I) */
|
||||
[P4_5] = { 4, 5, { .mode=0, .pd=1, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* RXENABLE/P56: MAX2837.RXENABLE(I) */
|
||||
[P4_6] = { 4, 6, { .mode=0, .pd=0, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* XCVR_EN: 10K PD, MAX2837.ENABLE(I) */
|
||||
[P4_7] = { 4, 7, { .mode=1, .pd=0, .pu=0, .fast=0, .input=1, .ifilt=0 } }, /* GP_CLKIN/P72/MCU_CLK: SI5351C.CLK7(O) */
|
||||
[P4_8] = { 4, 8, PinConfig::gpio_out_with_pullup(4) }, /* SGPIO13/BANK2F3M2: CPLD.90/HOST_DECIM_SEL0(I) */
|
||||
[P4_9] = { 4, 9, PinConfig::gpio_out_with_pullup(4) }, /* SGPIO14/BANK2F3M4: CPLD.81/HOST_DECIM_SEL1(I) */
|
||||
[P4_10] = { 4, 10, PinConfig::gpio_out_with_pullup(4) }, /* SGPIO15/BANK2F3M6: CPLD.78/HOST_DECIM_SEL2(I) */
|
||||
[P5_0] = { 5, 0, { .mode=0, .pd=0, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* !VAA_ENABLE: 10K PU, Q3.G(I), power to VAA */
|
||||
[P5_1] = { 5, 1, { .mode=0, .pd=1, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* LP/P45: U6.VCTL2(I), U5.VCTL1(I) */
|
||||
[P5_2] = { 5, 2, { .mode=0, .pd=0, .pu=1, .fast=0, .input=0, .ifilt=1 } }, /* TX_MIX_BP/P46: U9.V1(I) */
|
||||
[P5_3] = { 5, 3, { .mode=0, .pd=1, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* RX_MIX_BP/P47: U9.V3(I) */
|
||||
[P5_4] = { 5, 4, { .mode=0, .pd=0, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* MIXER_ENX/P32: 10K PU, 33pF, RFFC5072.ENX(I) */
|
||||
[P5_5] = { 5, 5, { .mode=0, .pd=0, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* MIXER_RESETX/P33: 10K PU, 33pF, RFFC5072.RESETX(I) */
|
||||
[P5_6] = { 5, 6, { .mode=0, .pd=1, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* TX_AMP/P48: U12.V3(I), U14.V1(I) */
|
||||
[P5_7] = { 5, 7, { .mode=0, .pd=0, .pu=1, .fast=0, .input=0, .ifilt=1 } }, /* CS_AD/P54: MAX5864.CS(I) */
|
||||
[P6_0] = { 6, 0, { .mode=0, .pd=0, .pu=1, .fast=0, .input=0, .ifilt=1 } }, /* I2S0_RX_MCLK: Unused */
|
||||
[P6_1] = { 6, 1, { .mode=0, .pd=1, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* CPLD_TCK: CPLD.TCK(I), PortaPack CPLD.TCK(I) */
|
||||
[P6_2] = { 6, 2, { .mode=0, .pd=0, .pu=1, .fast=0, .input=1, .ifilt=1 } }, /* CPLD_TDI: CPLD.TDI(I), PortaPack I2S0_RX_SDA(O), PortaPack CPLD.TDI(I) */
|
||||
[P6_3] = { 6, 3, PinConfig::sgpio_inout_fast(2) }, /* SGPIO4/BANK2F3M14: CPLD.67/HOST_DATA4(IO) */
|
||||
[P6_4] = { 6, 4, { .mode=0, .pd=0, .pu=0, .fast=0, .input=1, .ifilt=1 } }, /* MIXER_SDATA/P27: 33pF, RFFC5072.SDATA(IO) */
|
||||
[P6_5] = { 6, 5, { .mode=0, .pd=0, .pu=1, .fast=0, .input=0, .ifilt=1 } }, /* CPLD_TMS: CPLD.TMS(I) */
|
||||
[P6_6] = { 6, 6, PinConfig::sgpio_inout_fast(2) }, /* SGPIO5/BANK2F3M15: CPLD.64/HOST_DATA5(IO) */
|
||||
[P6_7] = { 6, 7, { .mode=4, .pd=0, .pu=1, .fast=0, .input=0, .ifilt=1 } }, /* TX/P42: U7.VCTL2(I), U10.VCTL2(I), U2.VCTL2(I) */
|
||||
[P6_8] = { 6, 8, { .mode=4, .pd=0, .pu=1, .fast=0, .input=0, .ifilt=1 } }, /* MIX_BYPASS/P34: U1.VCTL2(I), U11.VCTL1(I) */
|
||||
[P6_9] = { 6, 9, { .mode=0, .pd=0, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* !TX_AMP_PWR/P51: 10K PU, Q2.G(I), power to U25 (TX amp) */
|
||||
[P6_10] = { 6, 10, { .mode=0, .pd=0, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* EN1V8/P70: 10K PD, TPS62410.EN2(I), 1V8LED.A(I) */
|
||||
[P6_11] = { 6, 11, { .mode=0, .pd=1, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* VREGMODE/P69: TPS62410.MODE/DATA(I) */
|
||||
[P6_12] = { 6, 12, PinConfig::gpio_led(0) }, /* LED3: LED3.A(I) */
|
||||
[P7_0] = { 7, 0, PinConfig::gpio_inout_with_pulldown(0) }, /* GPIO3_8: PortaPack GPIO3_8(IO) */
|
||||
[P7_1] = { 7, 1, PinConfig::gpio_inout_with_pulldown(0) }, /* GPIO3_9: PortaPack GPIO3_9(IO) */
|
||||
[P7_2] = { 7, 2, PinConfig::gpio_inout_with_pulldown(0) }, /* GPIO3_10: PortaPack GPIO3_10(IO) */
|
||||
[P7_3] = { 7, 3, PinConfig::gpio_inout_with_pulldown(0) }, /* GPIO3_11: PortaPack GPIO3_11(IO) */
|
||||
[P7_4] = { 7, 4, PinConfig::gpio_inout_with_pulldown(0) }, /* GPIO3_12: PortaPack GPIO3_12(IO) */
|
||||
[P7_5] = { 7, 5, PinConfig::gpio_inout_with_pulldown(0) }, /* GPIO3_13: PortaPack GPIO3_13(IO) */
|
||||
[P7_6] = { 7, 6, PinConfig::gpio_inout_with_pulldown(0) }, /* GPIO3_14: PortaPack GPIO3_14(IO) */
|
||||
[P7_7] = { 7, 7, PinConfig::gpio_inout_with_pulldown(0) }, /* GPIO3_15: PortaPack GPIO3_15(IO) */
|
||||
[P9_5] = { 9, 5, { .mode=3, .pd=0, .pu=1, .fast=0, .input=1, .ifilt=1 } }, /* CPLD_TDO: CPLD.TDO(O) */
|
||||
[P9_6] = { 9, 6, PinConfig::sgpio_in_fast(6) }, /* SGPIO8/SGPIO_CLK/P60: SI5351C.CLK2(O) */
|
||||
[PF_4] = { 15, 4, { .mode=7, .pd=0, .pu=1, .fast=0, .input=0, .ifilt=1 } }, /* I2S0_RX_SCK: Unused */
|
||||
[CLK0] = { 24, 0, { .mode=4, .pd=1, .pu=0, .fast=1, .input=1, .ifilt=0 } }, /* SD_CLK: PortaPack SD.CLK, enable input buffer for timing feedback? */
|
||||
[CLK2] = { 24, 2, { .mode=6, .pd=1, .pu=0, .fast=0, .input=0, .ifilt=1 } }, /* I2S0_TX_CLK: PortaPack I2S0_TX_MCLK */
|
||||
};
|
||||
|
||||
enum GPIOs {
|
||||
GPIO0_0, GPIO0_1, GPIO0_2, GPIO0_3, GPIO0_4, GPIO0_5, /*GPIO0_6,*/ GPIO0_7, GPIO0_8, GPIO0_9, GPIO0_10, GPIO0_11, GPIO0_12, GPIO0_13, GPIO0_14, GPIO0_15,
|
||||
GPIO1_0, GPIO1_1, GPIO1_2, GPIO1_3, GPIO1_4, GPIO1_5, GPIO1_6, GPIO1_7, GPIO1_8, GPIO1_9, GPIO1_10, GPIO1_11, GPIO1_12, GPIO1_13, /*GPIO1_14, GPIO1_15,*/
|
||||
GPIO2_0, GPIO2_1, GPIO2_2, GPIO2_3, GPIO2_4, GPIO2_5, GPIO2_6, GPIO2_7, GPIO2_8, GPIO2_9, GPIO2_10, GPIO2_11, GPIO2_12, GPIO2_13, GPIO2_14, GPIO2_15,
|
||||
GPIO3_0, GPIO3_1, GPIO3_2, GPIO3_3, GPIO3_4, GPIO3_5, GPIO3_6, GPIO3_7, GPIO3_8, GPIO3_9, GPIO3_10, GPIO3_11, GPIO3_12, GPIO3_13, GPIO3_14, GPIO3_15,
|
||||
GPIO4_11,
|
||||
GPIO5_0, GPIO5_1, GPIO5_2, GPIO5_3, GPIO5_4, GPIO5_5, GPIO5_6, GPIO5_7, GPIO5_8, GPIO5_9, /*GPIO5_10, GPIO5_11,*/ GPIO5_12, GPIO5_13, GPIO5_14, GPIO5_15, GPIO5_16, GPIO5_18,
|
||||
};
|
||||
|
||||
constexpr GPIO gpio[] = {
|
||||
[GPIO0_0] = { pins[P0_0], 0, 0, 0 },
|
||||
[GPIO0_1] = { pins[P0_1], 0, 1, 0 },
|
||||
[GPIO0_2] = { pins[P1_15], 0, 2, 0 },
|
||||
[GPIO0_3] = { pins[P1_16], 0, 3, 0 },
|
||||
[GPIO0_4] = { pins[P1_0], 0, 4, 0 },
|
||||
[GPIO0_5] = { pins[P6_6], 0, 5, 0 },
|
||||
//[GPIO0_6] = { pins[P3_6], 0, 6, 0 },
|
||||
[GPIO0_7] = { pins[P2_7], 0, 7, 0 },
|
||||
[GPIO0_8] = { pins[P1_1], 0, 8, 0 },
|
||||
[GPIO0_9] = { pins[P1_2], 0, 9, 0 },
|
||||
[GPIO0_10] = { pins[P1_3], 0, 10, 0 },
|
||||
[GPIO0_11] = { pins[P1_4], 0, 11, 0 },
|
||||
[GPIO0_12] = { pins[P1_17], 0, 12, 0 },
|
||||
[GPIO0_13] = { pins[P1_18], 0, 13, 0 },
|
||||
[GPIO0_14] = { pins[P2_10], 0, 14, 0 },
|
||||
[GPIO0_15] = { pins[P1_20], 0, 15, 0 },
|
||||
|
||||
[GPIO1_0] = { pins[P1_7], 1, 0, 0 },
|
||||
[GPIO1_1] = { pins[P1_8], 1, 1, 0 },
|
||||
[GPIO1_2] = { pins[P1_9], 1, 2, 0 },
|
||||
[GPIO1_3] = { pins[P1_10], 1, 3, 0 },
|
||||
[GPIO1_4] = { pins[P1_11], 1, 4, 0 },
|
||||
[GPIO1_5] = { pins[P1_12], 1, 5, 0 },
|
||||
[GPIO1_6] = { pins[P1_13], 1, 6, 0 },
|
||||
[GPIO1_7] = { pins[P1_14], 1, 7, 0 },
|
||||
[GPIO1_8] = { pins[P1_5], 1, 8, 0 },
|
||||
[GPIO1_9] = { pins[P1_6], 1, 9, 0 },
|
||||
[GPIO1_10] = { pins[P2_9], 1, 10, 0 },
|
||||
[GPIO1_11] = { pins[P2_11], 1, 11, 0 },
|
||||
[GPIO1_12] = { pins[P2_12], 1, 12, 0 },
|
||||
[GPIO1_13] = { pins[P2_13], 1, 13, 0 },
|
||||
//[GPIO1_14] = { pins[P3_4], 1, 14, 0 },
|
||||
//[GPIO1_15] = { pins[P3_5], 1, 15, 0 },
|
||||
|
||||
[GPIO2_0] = { pins[P4_0], 2, 0, 0 },
|
||||
[GPIO2_1] = { pins[P4_1], 2, 1, 0 },
|
||||
[GPIO2_2] = { pins[P4_2], 2, 2, 0 },
|
||||
[GPIO2_3] = { pins[P4_3], 2, 3, 0 },
|
||||
[GPIO2_4] = { pins[P4_4], 2, 4, 0 },
|
||||
[GPIO2_5] = { pins[P4_5], 2, 5, 0 },
|
||||
[GPIO2_6] = { pins[P4_6], 2, 6, 0 },
|
||||
[GPIO2_7] = { pins[P5_7], 2, 7, 0 },
|
||||
[GPIO2_8] = { pins[P6_12], 2, 8, 0 },
|
||||
[GPIO2_9] = { pins[P5_0], 2, 9, 0 },
|
||||
[GPIO2_10] = { pins[P5_1], 2, 10, 0 },
|
||||
[GPIO2_11] = { pins[P5_2], 2, 11, 0 },
|
||||
[GPIO2_12] = { pins[P5_3], 2, 12, 0 },
|
||||
[GPIO2_13] = { pins[P5_4], 2, 13, 0 },
|
||||
[GPIO2_14] = { pins[P5_5], 2, 14, 0 },
|
||||
[GPIO2_15] = { pins[P5_6], 2, 15, 0 },
|
||||
|
||||
[GPIO3_0] = { pins[P6_1], 3, 0, 0 },
|
||||
[GPIO3_1] = { pins[P6_2], 3, 1, 0 },
|
||||
[GPIO3_2] = { pins[P6_3], 3, 2, 0 },
|
||||
[GPIO3_3] = { pins[P6_4], 3, 3, 0 },
|
||||
[GPIO3_4] = { pins[P6_5], 3, 4, 0 },
|
||||
[GPIO3_5] = { pins[P6_9], 3, 5, 0 },
|
||||
[GPIO3_6] = { pins[P6_10], 3, 6, 0 },
|
||||
[GPIO3_7] = { pins[P6_11], 3, 7, 0 },
|
||||
[GPIO3_8] = { pins[P7_0], 3, 8, 0 },
|
||||
[GPIO3_9] = { pins[P7_1], 3, 9, 0 },
|
||||
[GPIO3_10] = { pins[P7_2], 3, 10, 0 },
|
||||
[GPIO3_11] = { pins[P7_3], 3, 11, 0 },
|
||||
[GPIO3_12] = { pins[P7_4], 3, 12, 0 },
|
||||
[GPIO3_13] = { pins[P7_5], 3, 13, 0 },
|
||||
[GPIO3_14] = { pins[P7_6], 3, 14, 0 },
|
||||
[GPIO3_15] = { pins[P7_7], 3, 15, 0 },
|
||||
|
||||
[GPIO4_11] = { pins[P9_6], 4, 11, 0 },
|
||||
|
||||
[GPIO5_0] = { pins[P2_0], 5, 0, 4 },
|
||||
[GPIO5_1] = { pins[P2_1], 5, 1, 4 },
|
||||
[GPIO5_2] = { pins[P2_2], 5, 2, 4 },
|
||||
[GPIO5_3] = { pins[P2_3], 5, 3, 4 },
|
||||
[GPIO5_4] = { pins[P2_4], 5, 4, 4 },
|
||||
[GPIO5_5] = { pins[P2_5], 5, 5, 4 },
|
||||
[GPIO5_6] = { pins[P2_6], 5, 6, 4 },
|
||||
[GPIO5_7] = { pins[P2_8], 5, 7, 4 },
|
||||
[GPIO5_8] = { pins[P3_1], 5, 8, 4 },
|
||||
[GPIO5_9] = { pins[P3_2], 5, 9, 4 },
|
||||
//[GPIO5_10] = { pins[P3_7], 5, 10, 4 },
|
||||
//[GPIO5_11] = { pins[P3_8], 5, 11, 4 },
|
||||
[GPIO5_12] = { pins[P4_8], 5, 12, 4 },
|
||||
[GPIO5_13] = { pins[P4_9], 5, 13, 4 },
|
||||
[GPIO5_14] = { pins[P4_10], 5, 14, 4 },
|
||||
[GPIO5_15] = { pins[P6_7], 5, 15, 4 },
|
||||
[GPIO5_16] = { pins[P6_8], 5, 16, 4 },
|
||||
[GPIO5_18] = { pins[P9_5], 5, 18, 4 },
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif/*__PINS_H__*/
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __PORTAPACK_ADC_H__
|
||||
#define __PORTAPACK_ADC_H__
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace portapack {
|
||||
|
||||
/* ADC0 */
|
||||
|
||||
constexpr size_t adc0_touch_yp_input = 0;
|
||||
constexpr size_t adc0_touch_yn_input = 2;
|
||||
constexpr size_t adc0_touch_xp_input = 5;
|
||||
constexpr size_t adc0_touch_xn_input = 6;
|
||||
|
||||
/* ADC1 */
|
||||
|
||||
constexpr size_t adc1_rssi_input = 1;
|
||||
|
||||
} /* namespace portapack */
|
||||
|
||||
#endif/*__PORTAPACK_ADC_H__*/
|
||||
@@ -0,0 +1,519 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 "portapack_cpld_data.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
|
||||
namespace portapack {
|
||||
namespace cpld {
|
||||
|
||||
/* 2015 Apr 23 19:34 PT */
|
||||
|
||||
const std::array<uint16_t, 3328> block_0 { {
|
||||
0x7fff, 0xffff, 0xbffc, 0xf9e7, 0x79ff, 0xfffe, 0xaf9e, 0x7cff,
|
||||
0x7fff, 0xfbe7, 0xb3f7, 0xffff, 0x7f3f, 0x7dfb, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbff7, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x67ff, 0xffff, 0xbfff, 0xfefd, 0x7fff, 0xff7f, 0xbfff, 0xe7f9,
|
||||
0x623f, 0xfff9, 0xb77f, 0xcccf, 0x7fff, 0xb99f, 0xbccc, 0xcffe,
|
||||
0x6fff, 0xffff, 0xbfff, 0xffeb, 0x77f3, 0xffff, 0xbfe6, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fbf, 0xffff, 0xbfff, 0xfbfe,
|
||||
0x7fff, 0xffff, 0xbfff, 0xfffe, 0x6fff, 0xffff, 0xbfef, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x6fff, 0xffff, 0xbfff, 0xffdb, 0x7fff, 0xffff, 0xbff7, 0xffff,
|
||||
0x7eff, 0xefff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7ff5, 0xffff, 0xbffd, 0xffff,
|
||||
0x6fff, 0xefff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x6fff, 0xffff, 0xbfff, 0xfdbb, 0x77ef, 0xbfff, 0xbfff, 0xffff,
|
||||
0x7eef, 0xefff, 0xbfff, 0xffff, 0x7dff, 0xffff, 0xbfff, 0xfffe,
|
||||
0x7bff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbffd, 0xdfff,
|
||||
0x7dff, 0xefff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xfffe,
|
||||
0x7fff, 0xffff, 0xbfff, 0xff7f, 0x77ff, 0xffff, 0xbfff, 0xefff,
|
||||
0x7dff, 0xefff, 0xbfff, 0xffff, 0x7dff, 0xffff, 0xbfff, 0xfffe,
|
||||
0x7fff, 0xffff, 0xbfff, 0xfef7, 0x7ff7, 0xbfff, 0xbffd, 0xffff,
|
||||
0x7ef7, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xfffe,
|
||||
0x6fff, 0xffff, 0xbffe, 0xffdf, 0x7fff, 0xffbf, 0xbfff, 0xffff,
|
||||
0x7fff, 0xefff, 0xbfff, 0xffff, 0x7eff, 0xffff, 0xbfff, 0xffef,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xefff, 0xbfff, 0xffff, 0x7fff, 0xfebf, 0xbfff, 0xfeff,
|
||||
0x7fff, 0xffff, 0xb5fd, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbdff, 0xffbf, 0x7ffe, 0xffff, 0xbfef, 0xff5f,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffef, 0x7fff, 0xffdf, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7dff, 0xfd7f, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfdf, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xefff, 0xbfff, 0xffff, 0x7ff7, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xf6ef, 0xbfcb, 0xffff,
|
||||
0x77ff, 0xffff, 0xbfdf, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7ff7, 0xfdff, 0xbbff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xefff, 0xbfff, 0xffff, 0x7fff, 0xfbff, 0xbfd5, 0xffff,
|
||||
0x77ff, 0xffff, 0xa55f, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fdf, 0xdeef, 0xbfff, 0xfdff,
|
||||
0x7fff, 0xffff, 0xafff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7ffd, 0xffff, 0xbffb, 0xffeb,
|
||||
0x6bff, 0xffff, 0xb55f, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbdff, 0xdff5,
|
||||
0x77ff, 0xffff, 0xbabf, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7ffb, 0xf9bf, 0xbafe, 0xefff,
|
||||
0x6fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7ffe, 0xffde, 0xbfdf, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7ff7, 0xdfff, 0xbffd, 0x35ff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fd2, 0xffff, 0xbfbc, 0xc7ff,
|
||||
0x7fff, 0xffff, 0xb70f, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xddee, 0xb9ff, 0xbdff,
|
||||
0x7bff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7ffd, 0xea9f, 0xbefb, 0x7bff,
|
||||
0x7fff, 0xffff, 0xbeff, 0xffff, 0x7fdf, 0xffff, 0xbfff, 0xffef,
|
||||
0x7fff, 0xffff, 0xbfff, 0x7fff, 0x7ffd, 0x0ddf, 0xb598, 0x5e74,
|
||||
0x7fff, 0xffff, 0xb6ff, 0xffff, 0x7fbf, 0xffff, 0xbfff, 0xffdf,
|
||||
0x7fff, 0xffff, 0xbffe, 0xffff, 0x7ffc, 0x0ddd, 0xbd99, 0x1e6a,
|
||||
0x7fff, 0xffff, 0xbfaf, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7f08, 0x388f, 0xb89e, 0x887f,
|
||||
0x7bff, 0xffff, 0xb7f7, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7f0c, 0x388f, 0xb89f, 0x983b,
|
||||
0x67ff, 0xffff, 0xbfff, 0x3333, 0x63e6, 0x6667, 0xb333, 0x31f3,
|
||||
0x6666, 0x7ccc, 0xb98f, 0x9999, 0x73e8, 0xc445, 0xb938, 0x88ff,
|
||||
0x7fff, 0xffff, 0xb7ff, 0x7777, 0x6957, 0x7777, 0xb777, 0x74ab,
|
||||
0x7777, 0x7ddd, 0xbba5, 0x5ddd, 0x7bcd, 0xdcca, 0xb19d, 0xddfb,
|
||||
0x7bff, 0xffff, 0xbff7, 0xffff, 0x7fdf, 0xffff, 0xbfff, 0xffef,
|
||||
0x7fff, 0xffff, 0xbfff, 0x7fff, 0x7fff, 0xe66f, 0xb37f, 0xffde,
|
||||
0x7fff, 0xffff, 0xbffe, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xfffd,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7feb, 0xeedf, 0xbfdf, 0xfcff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xeeee, 0x7ffb, 0xfbbf, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7dfd, 0xffff, 0xbffd, 0xdfff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xfffd,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7ffa, 0xefdf, 0xbfff, 0xdfff,
|
||||
0x7fff, 0xffff, 0xbbfe, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fef, 0xfeff, 0xbfdd, 0xfd7a,
|
||||
0x77ff, 0xffff, 0xbebe, 0xfff7, 0x7fff, 0xfb7f, 0xbf9f, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfef, 0xfffb,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbaff, 0xfffd,
|
||||
0x7fff, 0xedff, 0xbfff, 0xffde, 0x7ffb, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xb7fd, 0xfff7, 0x7fff, 0xfdfb, 0xb7ff, 0xffff,
|
||||
0x7fff, 0xfdff, 0xbfff, 0xffff, 0x7ffe, 0xffff, 0xbff3, 0xbbf7,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xff7f, 0xbeaf, 0xfffe,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffbe, 0x7ffb, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfee, 0xf7f7, 0x7fff, 0xfbef, 0xbfff, 0xffff,
|
||||
0x7fff, 0xfbfe, 0xbdff, 0xfadf, 0x7dff, 0xffff, 0xbfff, 0xffdf,
|
||||
0x7fff, 0xffff, 0xb7ff, 0x6fff, 0x77ff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xfff7, 0xafff, 0xbfef, 0x7fff, 0xffff, 0xbfff, 0xfffb,
|
||||
0x7fff, 0xffff, 0xbffd, 0xdfff, 0x7ff7, 0xfdff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffd7, 0x7eff, 0xffff, 0xbfff, 0xffdf,
|
||||
0x7fff, 0xffff, 0xbbdf, 0xbbf7, 0x7fff, 0xffef, 0xbfff, 0xffff,
|
||||
0x7fff, 0xfbf9, 0xb5ff, 0xfcff, 0x7fff, 0xffff, 0xbfff, 0xfffb,
|
||||
0x7fff, 0xffff, 0xbeff, 0xff77, 0x7fff, 0xf7fd, 0xbfff, 0xffff,
|
||||
0x7fff, 0xfeee, 0xbfbf, 0xfb3b, 0x77ff, 0xffff, 0xbfff, 0xffea,
|
||||
0x7fff, 0xffff, 0xbbaf, 0xffff, 0x6fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xf77f, 0xbfff, 0xd7f7, 0x6eff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7bff, 0xffff, 0xbb5f, 0xffff, 0x7ff7, 0x7fff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xfff7, 0xaaff, 0xf77f, 0x7fff, 0xffff, 0xbfff, 0xfff4,
|
||||
0x7fff, 0xffff, 0xbdaf, 0x7bff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xf7be, 0xbbff, 0xffff, 0x6dff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7bff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xfeff, 0xbfbf, 0xfff3, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7f7f, 0xff7f, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffef, 0xbfff, 0xffbf, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xff7f, 0x7fff, 0xfffd, 0xbfff, 0xffff,
|
||||
0x7fff, 0xfcde, 0xbdbf, 0xdf8d, 0x7bff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xb5af, 0xbfff, 0x6ff7, 0x76ff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xfbad, 0xbfdf, 0xf77b, 0x7fff, 0xffff, 0xbfff, 0xffee,
|
||||
0x77ff, 0xffff, 0xbfff, 0xfbf7, 0x7f7f, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xf77b, 0xb37f, 0xecf6, 0x6cff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbf5f, 0x3000, 0x67c0, 0x007f, 0xbfff, 0xffef,
|
||||
0x7fff, 0xfccd, 0xbbb7, 0x7f99, 0x7cff, 0xffff, 0xb7ff, 0xfff5,
|
||||
0x6bff, 0xffff, 0xb7af, 0x3000, 0x66e0, 0x0061, 0xbfff, 0xffdf,
|
||||
0x7fff, 0xfccd, 0xbbbe, 0xd519, 0x7cff, 0xffff, 0xafff, 0xffff,
|
||||
0x7dff, 0xffff, 0xbdff, 0x3000, 0x67e0, 0x007f, 0xbfff, 0xffff,
|
||||
0x7fff, 0xfcc8, 0xb11f, 0xcc99, 0x7cff, 0xffff, 0xbfff, 0xfff5,
|
||||
0x6bff, 0xffff, 0xbbbf, 0x3000, 0x67e0, 0x0061, 0xbfff, 0xffff,
|
||||
0x7fff, 0xf698, 0xb11f, 0x8033, 0x66ff, 0xffff, 0xbfff, 0xffff,
|
||||
0x77ff, 0xffff, 0xbff7, 0xbbbb, 0x73ee, 0x6ee7, 0xb333, 0x31f3,
|
||||
0x6666, 0x78c6, 0xaccf, 0xb318, 0x7bcc, 0xccc7, 0xb999, 0x99ff,
|
||||
0x7fff, 0xffff, 0xb77f, 0x3333, 0x6546, 0x6667, 0xb777, 0x74ab,
|
||||
0x7777, 0x7d9c, 0xb995, 0x19cd, 0x79dd, 0xddd2, 0xb5dd, 0xddff,
|
||||
0x7bff, 0xffff, 0xbffb, 0xfddd, 0x7fdd, 0xddff, 0xbfff, 0xffef,
|
||||
0x7fff, 0xfff6, 0xacff, 0x337f, 0x7fff, 0xffff, 0xb7ff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbffd, 0x5fff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xfff9, 0xbbdf, 0xddff, 0x7bbf, 0xbfff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xfff7, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xfdff, 0xbfff, 0xfffd, 0x6fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbffe, 0xfffb, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfbf, 0xfffd, 0x6fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7dff, 0xffff, 0xbbff, 0x5fff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xfef5, 0xbbff, 0xbdff, 0x77bf, 0xbfff, 0xbfff, 0xffef,
|
||||
0x7dff, 0xffff, 0xbfbf, 0xffef, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7ffd, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xdfff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7ffb, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xefff, 0xbfff, 0xffff, 0x7ff7, 0xffbf, 0xbfff, 0xfdff,
|
||||
0x7fff, 0xffff, 0xbff7, 0xffdf, 0x7ffe, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xeeff, 0xbfff, 0xffff, 0x7ff7, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7ffd, 0xffff, 0xbfff, 0xffff,
|
||||
0x7ffd, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xdfbf, 0xbfff, 0xfdff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xefff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbf7f, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xefff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfbf, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfbf, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xfffd,
|
||||
0x7bff, 0xffff, 0xb7ff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbf7f, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xfffd,
|
||||
0x79ff, 0xffff, 0xb7bf, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x75ff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbebf, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xfffe,
|
||||
0x77ff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xa95f, 0xffff, 0x7fdf, 0xffff, 0xbfff, 0xffef,
|
||||
0x7fff, 0xffff, 0xbfff, 0x7fff, 0x7fff, 0xffff, 0xb7ff, 0xfff5,
|
||||
0x69ff, 0xffff, 0xa7ff, 0xffff, 0x7fbf, 0xffff, 0xbfff, 0xffdf,
|
||||
0x7fff, 0xffff, 0xbffe, 0xffff, 0x7fff, 0xffff, 0xafff, 0xffff,
|
||||
0x7dff, 0xffff, 0xbd9f, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xfff5,
|
||||
0x6bff, 0xffff, 0xbaff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0x3333, 0x63e6, 0x6667, 0xb333, 0x31f3,
|
||||
0x6666, 0x7ccc, 0xb98f, 0x9999, 0x73cc, 0xccc7, 0xb999, 0x99ff,
|
||||
0x7fff, 0xffff, 0xb7ff, 0x7777, 0x6957, 0x7777, 0xb777, 0x74ab,
|
||||
0x7777, 0x7ddd, 0xbba5, 0x5ddd, 0x7bdd, 0xddd2, 0xb5dd, 0xddff,
|
||||
0x7fff, 0xffff, 0xbdff, 0xffff, 0x7fdf, 0xffff, 0xbfff, 0xffef,
|
||||
0x7fff, 0xffff, 0xbfff, 0x7fff, 0x7fff, 0xffff, 0xb7ff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbffd, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xf7ff, 0x7fff, 0xfbff, 0xbfff, 0xf7ff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbffe, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xfbff, 0xbfff, 0xffff,
|
||||
0x7dff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xefff, 0x7fff, 0xffff, 0xbfff, 0xf7ff,
|
||||
0x7dff, 0xffff, 0xbbbf, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbeff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xefff,
|
||||
0x7fff, 0xefff, 0xbfff, 0xffff, 0x7fff, 0xfbff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbff7, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xefff, 0xbfff, 0xffff, 0x7fff, 0xf7ff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xefff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbeff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xefff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffbf,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xefff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xfffb,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xfffd,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffbf,
|
||||
0x7fff, 0xffff, 0xaddf, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xfff5,
|
||||
0x69ff, 0xffff, 0xab7f, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7dff, 0xffff, 0xbddf, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xfff5,
|
||||
0x69ff, 0xffff, 0xb63f, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xfffe,
|
||||
0x75ff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbf0f, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xfff5,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xb6ff, 0xffff, 0x7fdf, 0xffff, 0xbfff, 0xffef,
|
||||
0x7fff, 0xffff, 0xbfff, 0x7fff, 0x7fff, 0xffff, 0xb7ff, 0xfffe,
|
||||
0x7bff, 0xffff, 0xb95f, 0xffff, 0x7fbf, 0xffff, 0xbfff, 0xffdf,
|
||||
0x7fff, 0xffff, 0xbffe, 0xffff, 0x7fff, 0xffff, 0xafff, 0xffeb,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xfffe,
|
||||
0x77ff, 0xffff, 0xb69f, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffef,
|
||||
0x7fff, 0xffff, 0xbfff, 0x3333, 0x63e6, 0x6667, 0xb333, 0x31f3,
|
||||
0x6666, 0x7ccc, 0xb98f, 0x9999, 0x73cc, 0xccc7, 0xb999, 0x99ff,
|
||||
0x7fff, 0xffff, 0xb7bf, 0x7777, 0x6957, 0x7777, 0xb777, 0x74ab,
|
||||
0x7777, 0x7ddd, 0xbba5, 0x5ddd, 0x7bdd, 0xddd2, 0xb5dd, 0xddff,
|
||||
0x7fff, 0xffff, 0xbedf, 0xffff, 0x7fdf, 0xffff, 0xbfff, 0xffef,
|
||||
0x7fff, 0xffff, 0xbfff, 0x7fff, 0x7fff, 0xffff, 0xb7ff, 0xfff7,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbeff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xfffe, 0x7ff7, 0xffbf, 0xbeff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xff5f,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x6ff7, 0xffff, 0xbf7f, 0xfeff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbdff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xff7f, 0xbfff, 0xffff,
|
||||
0x77ff, 0xffff, 0xbffb, 0xff7f, 0x7fff, 0xbbf7, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xfffb, 0x7ff7, 0xffff, 0xbfff, 0xffbf,
|
||||
0x7fff, 0xffff, 0xbffe, 0xffff, 0x7fff, 0xffff, 0xbffe, 0xffff,
|
||||
0x7fff, 0xefff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbdfd, 0xffff, 0x7fff, 0xdff7, 0xbfff, 0xffff,
|
||||
0x7fff, 0xefff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffbf, 0x7fff, 0xfdff, 0xbffe, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xfffb, 0x7ffb, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfee, 0x75ff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffdf,
|
||||
0x7fff, 0xffff, 0xb7ff, 0xffff, 0x7ff7, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xefff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbffd, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xb7df, 0xb5ff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffbf,
|
||||
0x7fff, 0xffff, 0xb65f, 0xefff, 0x7fff, 0x7fff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xfff5,
|
||||
0x6bff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7dff, 0xffff, 0xb7ff, 0xfdff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xfff5,
|
||||
0x6bff, 0xffff, 0xbd0f, 0xffff, 0x7ff7, 0xffdf, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffea,
|
||||
0x77ff, 0xffff, 0xbbff, 0xffff, 0x7fff, 0xffff, 0x9fff, 0xffff,
|
||||
0x5fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0x9fff, 0xffff, 0x4fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0x9fff, 0xffff,
|
||||
0x5fff, 0xffff, 0xbfff, 0xdeff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbaff, 0xffff, 0x77ff, 0xffbf, 0x9fff, 0xffff,
|
||||
0x5fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xfffe,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fef, 0x7fff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xa55f, 0xfebf, 0x67c6, 0x1ebf, 0xbfff, 0xffef,
|
||||
0x7fff, 0xffff, 0x9fff, 0x7fff, 0x5fff, 0xffff, 0xb7ff, 0xfff5,
|
||||
0x65ff, 0xffff, 0xafff, 0xc2bf, 0x47a6, 0x1ebf, 0xbfff, 0xffdf,
|
||||
0x7fff, 0xffff, 0xbffe, 0xffff, 0x7fff, 0xffff, 0xafff, 0xffff,
|
||||
0x5dff, 0xffff, 0xb55f, 0xfe7f, 0x67e6, 0x1f3f, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xfff5,
|
||||
0x67ff, 0xffff, 0x9fff, 0xc27f, 0x47e6, 0x1f3f, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x5fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0x3bb3, 0x73ee, 0xe6e7, 0xb333, 0x31f3,
|
||||
0x4666, 0x7ccc, 0xb98f, 0x9999, 0x73cc, 0xccc7, 0xb999, 0x99ff,
|
||||
0x7fff, 0xffff, 0xbfff, 0x7337, 0x4546, 0x7677, 0xb777, 0x74ab,
|
||||
0x7777, 0x7ddd, 0xbba5, 0x5ddd, 0x7bdd, 0xddd2, 0xb5dd, 0xddff,
|
||||
0x5fff, 0xffff, 0xbfff, 0xffff, 0x7fdf, 0xdfff, 0xbfff, 0xffef,
|
||||
0x7fff, 0xffff, 0xbfff, 0x7fff, 0x7fff, 0xffff, 0xb7ff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xfeff, 0x77ff, 0xffff, 0xbfff, 0xefff,
|
||||
0x7fff, 0xffff, 0xbf7f, 0xfff7, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0x9fff, 0xffff, 0x7ff7, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fdf, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xff7f, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0x8fff, 0xfdff, 0x4ff7, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fbf, 0xffff, 0xbfff, 0xffef, 0x7fff, 0xff7f, 0x9fff, 0xffff,
|
||||
0x5dff, 0xffff, 0xafff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xefff,
|
||||
0x7fff, 0xffff, 0x9f7f, 0xffff, 0x5fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7dff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0x9fff, 0xffff,
|
||||
0x5fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xfffb,
|
||||
0x77ff, 0xffff, 0x9fff, 0xffff, 0x5fff, 0xffff, 0xbfff, 0xdfff,
|
||||
0x7fff, 0xefff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0x9fff, 0xffff,
|
||||
0x5fff, 0xffff, 0xbfff, 0xffff, 0x77ee, 0xffff, 0xbfff, 0xdfff,
|
||||
0x7fff, 0xefff, 0x9fff, 0xffff, 0x5fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0x9fff, 0xffff, 0x5fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xefff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xefff, 0x9fff, 0xffff, 0x5fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0x9fff, 0xffff,
|
||||
0x5fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0x9fff, 0xffff, 0x5fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0x9fff, 0xffff,
|
||||
0x5fff, 0xffff, 0xa55f, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0x9fff, 0xffff, 0x5fff, 0xffff, 0xbfff, 0xfffd,
|
||||
0x7bff, 0xffff, 0xafff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xa55f, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xfffd,
|
||||
0x7bff, 0xffff, 0xaaff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xfffb,
|
||||
0x77ff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0x9fff, 0xffff, 0x5fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0x9fff, 0xffff,
|
||||
0x5fff, 0xffff, 0xbaff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0x9fff, 0xffff, 0x5fff, 0xffff, 0xbfff, 0xffee,
|
||||
0x77ff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0x9fff, 0xffff,
|
||||
0x5fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0x855f, 0xffff, 0x5fdf, 0xffff, 0xbfff, 0xffef,
|
||||
0x7fff, 0xffff, 0xbfff, 0x7fff, 0x7fff, 0xffff, 0x97ff, 0xfff5,
|
||||
0x4bff, 0xffff, 0xafff, 0xffff, 0x7fbf, 0xffff, 0xbfff, 0xffdf,
|
||||
0x7fff, 0xffff, 0xbffe, 0xffff, 0x7fff, 0xffff, 0xafff, 0xffff,
|
||||
0x7fff, 0xffff, 0xb55f, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xfff5,
|
||||
0x6bff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x5fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0x3333, 0x43e6, 0x6667, 0xb333, 0x31f3,
|
||||
0x6666, 0x7ccc, 0xb98f, 0x9999, 0x73cc, 0xccc7, 0xb999, 0x99ff,
|
||||
0x7fff, 0xffff, 0xbfff, 0x7777, 0x6957, 0x7777, 0xb777, 0x74ab,
|
||||
0x7777, 0x7ddd, 0xbba5, 0x5ddd, 0x7bdd, 0xddd2, 0xb5dd, 0xddff,
|
||||
0x7fff, 0xffff, 0x9fff, 0xffff, 0x5fdf, 0xffff, 0xbfff, 0xffef,
|
||||
0x7fff, 0xffff, 0xbfff, 0x7fff, 0x7fff, 0xffff, 0xb7ff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0x9fff, 0xfeff, 0x7fff, 0xbfff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffbf, 0x9fff, 0xfff7,
|
||||
0x7fff, 0xffff, 0xafff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0x9fff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7dff, 0xffff, 0xafff, 0xffff, 0x5fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7dff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xf7ff,
|
||||
0x7fff, 0xffff, 0xbfbf, 0xffff, 0x5fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffef, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x5fff, 0xefff, 0xbfff, 0xffef, 0x7fff, 0xffbf, 0x9fff, 0xffff,
|
||||
0x5fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xf7ff,
|
||||
0x7fff, 0xefff, 0x9fff, 0xffff, 0x5fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfdf, 0xffff, 0x5fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fef, 0xffff, 0x9fff, 0xe7ff,
|
||||
0x5fff, 0xefff, 0xbfff, 0xdfff, 0x7fff, 0xffff, 0x9fff, 0xffff,
|
||||
0x5fff, 0xffff, 0xbfff, 0xffbe, 0x7fff, 0xbdff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xefff, 0x9fff, 0xffff, 0x5fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xfffd, 0x7ff7, 0xfdff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xdfff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xff7f, 0x7fff, 0xdfff, 0xbfff, 0xd7ff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffef, 0x7ffd, 0xdfff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xefff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xfffb, 0x77ef, 0xffff, 0xbfdd, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xfffe, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0x9fff, 0xffef, 0x5ffd, 0xbfff, 0xbfef, 0xffff,
|
||||
0x7fff, 0xffff, 0x9fff, 0xefff, 0x5fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xfef1, 0x67e7, 0xbfff, 0x9fed, 0xeffd,
|
||||
0x53ff, 0xfff9, 0xb77f, 0xffff, 0x7fff, 0xb99f, 0xbccf, 0xffff,
|
||||
0x7fff, 0xffff, 0x9fff, 0xffff, 0x5fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0x9fff, 0xffff,
|
||||
0x5fff, 0xffff, 0xbffc, 0xffff, 0x7ff3, 0xfffe, 0xaf9e, 0x7cff,
|
||||
0x7fff, 0xffe7, 0x93e7, 0xffff, 0x5f3e, 0x79f3, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0x9fff, 0xffff,
|
||||
0x5fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
0x7fff, 0xffff, 0xbfff, 0xffff, 0x7fff, 0xffff, 0xbfff, 0xffff,
|
||||
} };
|
||||
|
||||
const std::array<uint16_t, 512> block_1 { {
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||
} };
|
||||
|
||||
} /* namespace cpld */
|
||||
} /* namespace portapack */
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __PORTAPACK_CPLD_DATA_H__
|
||||
#define __PORTAPACK_CPLD_DATA_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
|
||||
namespace portapack {
|
||||
namespace cpld {
|
||||
|
||||
extern const std::array<uint16_t, 3328> block_0;
|
||||
extern const std::array<uint16_t, 512> block_1;
|
||||
|
||||
} /* namespace cpld */
|
||||
} /* namespace portapack */
|
||||
|
||||
#endif/*__PORTAPACK_CPLD_DATA_H__*/
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __PORTAPACK_DMA_H__
|
||||
#define __PORTAPACK_DMA_H__
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "gpdma.hpp"
|
||||
using namespace lpc43xx;
|
||||
|
||||
namespace portapack {
|
||||
|
||||
/* GPDMA */
|
||||
|
||||
/* DMA channel 0 has the highest priority and DMA channel 7 has the lowest
|
||||
* priority.
|
||||
*/
|
||||
/* Reserve channels 6 and 7 for memory-memory transfers. These channels
|
||||
* can't saturate AHB by design. */
|
||||
|
||||
constexpr size_t sgpio_gpdma_channel_number = 0;
|
||||
constexpr size_t i2s0_tx_gpdma_channel_number = 2;
|
||||
constexpr size_t i2s0_rx_gpdma_channel_number = 3;
|
||||
constexpr size_t adc1_gpdma_channel_number = 4;
|
||||
constexpr size_t adc0_gpdma_channel_number = 5;
|
||||
|
||||
constexpr gpdma::mux::MUX gpdma_mux {
|
||||
.peripheral_0 = gpdma::mux::Peripheral0::SGPIO14,
|
||||
.peripheral_1 = gpdma::mux::Peripheral1::TIMER0_MATCH_0,
|
||||
.peripheral_2 = gpdma::mux::Peripheral2::TIMER0_MATCH_1,
|
||||
.peripheral_3 = gpdma::mux::Peripheral3::TIMER1_MATCH_0,
|
||||
.peripheral_4 = gpdma::mux::Peripheral4::TIMER1_MATCH_1,
|
||||
.peripheral_5 = gpdma::mux::Peripheral5::TIMER2_MATCH_0,
|
||||
.peripheral_6 = gpdma::mux::Peripheral6::TIMER2_MATCH_1,
|
||||
.peripheral_7 = gpdma::mux::Peripheral7::TIMER3_MATCH_0,
|
||||
.peripheral_8 = gpdma::mux::Peripheral8::TIMER3_MATCH_1,
|
||||
.peripheral_9 = gpdma::mux::Peripheral9::I2S0_DMAREQ_1,
|
||||
.peripheral_10 = gpdma::mux::Peripheral10::I2S0_DMAREQ_2,
|
||||
.peripheral_11 = gpdma::mux::Peripheral11::SSP1_RX,
|
||||
.peripheral_12 = gpdma::mux::Peripheral12::SSP1_TX,
|
||||
.peripheral_13 = gpdma::mux::Peripheral13::ADC0,
|
||||
.peripheral_14 = gpdma::mux::Peripheral14::ADC1,
|
||||
.peripheral_15 = gpdma::mux::Peripheral15::DAC,
|
||||
};
|
||||
|
||||
} /* namespace portapack */
|
||||
|
||||
#endif/*__PORTAPACK_DMA_H__*/
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __PORTAPACK_HAL_H__
|
||||
#define __PORTAPACK_HAL_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <array>
|
||||
|
||||
#include "pins.hpp"
|
||||
using namespace lpc43xx;
|
||||
|
||||
namespace portapack {
|
||||
|
||||
/* TODO: Make these GPIOs private and expose via appropriate functions. */
|
||||
|
||||
constexpr GPIO gpio_io_stbx = gpio[GPIO5_0]; /* P2_0 */
|
||||
constexpr GPIO gpio_addr = gpio[GPIO5_1]; /* P2_1 */
|
||||
constexpr GPIO gpio_lcd_te = gpio[GPIO5_3]; /* P2_3 */
|
||||
constexpr GPIO gpio_unused = gpio[GPIO5_4]; /* P2_4 */
|
||||
constexpr GPIO gpio_lcd_rd = gpio[GPIO5_7]; /* P2_8 */
|
||||
constexpr GPIO gpio_lcd_wr = gpio[GPIO1_10]; /* P2_9 */
|
||||
constexpr GPIO gpio_dir = gpio[GPIO1_13]; /* P2_13 */
|
||||
constexpr std::array<GPIO, 8> gpios_data {
|
||||
gpio[GPIO3_8],
|
||||
gpio[GPIO3_9],
|
||||
gpio[GPIO3_10],
|
||||
gpio[GPIO3_11],
|
||||
gpio[GPIO3_12],
|
||||
gpio[GPIO3_13],
|
||||
gpio[GPIO3_14],
|
||||
gpio[GPIO3_15],
|
||||
};
|
||||
|
||||
constexpr GPIO gpio_cpld_tms = gpio[GPIO1_1]; // P1_8
|
||||
constexpr GPIO gpio_cpld_tdo = gpio[GPIO1_8]; // P1_5
|
||||
constexpr GPIO gpio_cpld_tck = gpio[GPIO3_0]; // P6_1
|
||||
constexpr GPIO gpio_cpld_tdi = gpio[GPIO3_1]; // P6_2
|
||||
|
||||
/* I2C0 */
|
||||
|
||||
constexpr uint8_t wm8731_i2c_address = 0x1a;
|
||||
|
||||
} /* namespace portapack */
|
||||
|
||||
#endif/*__PORTAPACK_HAL_H__*/
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 "portapack_io.hpp"
|
||||
|
||||
#include "lpc43xx_cpp.hpp"
|
||||
using namespace lpc43xx;
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <ch.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace portapack {
|
||||
|
||||
void IO::init() {
|
||||
data_mask_set();
|
||||
data_write_high(0);
|
||||
|
||||
dir_read();
|
||||
lcd_rd_deassert();
|
||||
lcd_wr_deassert();
|
||||
io_stb_deassert();
|
||||
addr(0);
|
||||
|
||||
gpio_dir.output();
|
||||
gpio_lcd_rd.output();
|
||||
gpio_lcd_wr.output();
|
||||
gpio_io_stbx.output();
|
||||
gpio_addr.output();
|
||||
gpio_rot_a.input();
|
||||
gpio_rot_b.input();
|
||||
}
|
||||
|
||||
void IO::lcd_backlight(const bool value) {
|
||||
io_reg = (io_reg & 0x7f) | ((value ? 1 : 0) << 7);
|
||||
io_write(1, io_reg);
|
||||
}
|
||||
|
||||
void IO::lcd_reset_state(const bool active) {
|
||||
/* NOTE: This overwrites the contents of the IO register, which for now
|
||||
* have no significance. But someday...?
|
||||
*/
|
||||
io_reg = (io_reg & 0xfe) | ((active ? 1 : 0) << 0);
|
||||
io_write(1, io_reg);
|
||||
}
|
||||
|
||||
uint32_t IO::io_update(const TouchPinsConfig write_value) {
|
||||
/* Very touchy code to save context of PortaPack data bus while the
|
||||
* resistive touch pin drive is changed. Order of operations is
|
||||
* important to prevent latching spurious data into the LCD or IO
|
||||
* registers.
|
||||
*/
|
||||
|
||||
const auto save_data = data_read();
|
||||
const auto addr = gpio_addr.read();
|
||||
const auto dir = gpio_dir.read();
|
||||
|
||||
io_stb_assert();
|
||||
|
||||
/* Switch to read */
|
||||
dir_read();
|
||||
addr_0();
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
const auto switches_raw = data_read();
|
||||
|
||||
/* Switch to write */
|
||||
data_write_low(toUType(write_value));
|
||||
dir_write();
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
io_stb_deassert();
|
||||
|
||||
data_write_low(save_data);
|
||||
if( dir ) { /* 0 (write) -> 1 (read) */
|
||||
dir_read();
|
||||
}
|
||||
gpio_addr.write(addr);
|
||||
|
||||
return switches_raw;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,381 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __PORTAPACK_IO_H__
|
||||
#define __PORTAPACK_IO_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <array>
|
||||
|
||||
#include "gpio.hpp"
|
||||
#include "ui.hpp"
|
||||
|
||||
namespace portapack {
|
||||
|
||||
class IO {
|
||||
public:
|
||||
enum class TouchPinsConfig : uint8_t {
|
||||
XN_BIT = (1 << 0),
|
||||
XP_BIT = (1 << 1),
|
||||
YN_BIT = (1 << 2),
|
||||
YP_BIT = (1 << 3),
|
||||
|
||||
XN_OE = (1 << 4),
|
||||
XP_OE = (1 << 5),
|
||||
YN_OE = (1 << 6),
|
||||
YP_OE = (1 << 7),
|
||||
|
||||
XN_IN = XN_BIT,
|
||||
XN_OUT_1 = XN_OE | XN_BIT,
|
||||
XN_OUT_0 = XN_OE,
|
||||
|
||||
XP_IN = XP_BIT,
|
||||
XP_OUT_1 = XP_OE | XP_BIT,
|
||||
XP_OUT_0 = XP_OE,
|
||||
|
||||
YN_IN = YN_BIT,
|
||||
YN_OUT_1 = YN_OE | YN_BIT,
|
||||
YN_OUT_0 = YN_OE,
|
||||
|
||||
YP_IN = YP_BIT,
|
||||
YP_OUT_1 = YP_OE | YP_BIT,
|
||||
YP_OUT_0 = YP_OE,
|
||||
|
||||
/* Allow pins to be pulled up by CPLD pull-ups. */
|
||||
Float = XP_IN | XN_IN | YP_IN | YN_IN,
|
||||
|
||||
/* Drive one plane to 0V, other plane is pulled up. Watch for when pulled-up
|
||||
* plane falls to ~0V.
|
||||
*/
|
||||
WaitTouch = XP_OUT_0 | XN_OUT_0 | YP_IN | YN_IN,
|
||||
|
||||
/* Create a voltage divider between X plane, touch resistance, Y plane. */
|
||||
SensePressure = XP_IN | XN_OUT_0 | YP_OUT_1 | YN_IN,
|
||||
|
||||
/* Create a voltage divider across X plane, read voltage from Y plane. */
|
||||
SenseX = XP_OUT_1 | XN_OUT_0 | YP_IN | YN_IN,
|
||||
|
||||
/* Create a voltage divider across Y plane, read voltage from X plane. */
|
||||
SenseY = XP_IN | XN_IN | YP_OUT_1 | YN_OUT_0,
|
||||
};
|
||||
|
||||
constexpr IO(
|
||||
GPIO gpio_dir,
|
||||
GPIO gpio_lcd_rd,
|
||||
GPIO gpio_lcd_wr,
|
||||
GPIO gpio_io_stbx,
|
||||
GPIO gpio_addr,
|
||||
GPIO gpio_rot_a,
|
||||
GPIO gpio_rot_b
|
||||
) : gpio_dir { gpio_dir },
|
||||
gpio_lcd_rd { gpio_lcd_rd },
|
||||
gpio_lcd_wr { gpio_lcd_wr },
|
||||
gpio_io_stbx { gpio_io_stbx },
|
||||
gpio_addr { gpio_addr },
|
||||
gpio_rot_a { gpio_rot_a },
|
||||
gpio_rot_b { gpio_rot_b }
|
||||
{
|
||||
};
|
||||
|
||||
void init();
|
||||
|
||||
void lcd_backlight(const bool value);
|
||||
void lcd_reset_state(const bool active);
|
||||
|
||||
void lcd_data_write_command_and_data(
|
||||
const uint_fast8_t command,
|
||||
const std::initializer_list<uint8_t>& data
|
||||
) {
|
||||
lcd_command(command);
|
||||
for(const auto d : data) {
|
||||
lcd_write_data_fast(d);
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_data_read_command_and_data(
|
||||
const uint_fast8_t command,
|
||||
uint16_t* const data,
|
||||
const size_t data_count
|
||||
) {
|
||||
lcd_command(command);
|
||||
for(size_t i=0; i<data_count; i++) {
|
||||
data[i] = lcd_read_data_id();
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_write_word(const uint32_t w) {
|
||||
lcd_write_data_fast(w);
|
||||
}
|
||||
|
||||
void lcd_write_words(const uint16_t* const w, size_t n) {
|
||||
for(size_t i=0; i<n; i++) {
|
||||
lcd_write_data_fast(w[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_write_pixel(const ui::Color pixel) {
|
||||
lcd_write_data_fast(pixel.v);
|
||||
}
|
||||
|
||||
uint32_t lcd_read_word() {
|
||||
return lcd_read_data_frame_memory();
|
||||
}
|
||||
/*
|
||||
// NOTE: Pixels read in RGB24 format, not the RGB565 format used
|
||||
// to write pixels to frame memory. This makes reading very tricky!
|
||||
ui::Color lcd_read_pixel() {
|
||||
return ui::Color { lcd_read_data_frame_memory() };
|
||||
}
|
||||
*/
|
||||
void lcd_write_pixels(const ui::Color pixel, size_t n) {
|
||||
while(n--) {
|
||||
lcd_write_data_fast(pixel.v);
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_write_pixels(const ui::Color* const pixels, size_t n) {
|
||||
for(size_t i=0; i<n; i++) {
|
||||
lcd_write_pixel(pixels[i]);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t io_read() {
|
||||
io_stb_assert();
|
||||
dir_read();
|
||||
addr_0();
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
const auto switches_raw = data_read();
|
||||
io_stb_deassert();
|
||||
|
||||
return switches_raw;
|
||||
}
|
||||
|
||||
uint32_t io_update(const TouchPinsConfig write_value);
|
||||
|
||||
uint32_t lcd_te() {
|
||||
return gpio_rot_a.read();
|
||||
}
|
||||
|
||||
private:
|
||||
const GPIO gpio_dir;
|
||||
const GPIO gpio_lcd_rd;
|
||||
const GPIO gpio_lcd_wr;
|
||||
const GPIO gpio_io_stbx;
|
||||
const GPIO gpio_addr;
|
||||
const GPIO gpio_rot_a;
|
||||
const GPIO gpio_rot_b;
|
||||
|
||||
static constexpr ioportid_t gpio_data_port_id = 3;
|
||||
static constexpr size_t gpio_data_shift = 8;
|
||||
static constexpr ioportmask_t gpio_data_mask = 0xffU << gpio_data_shift;
|
||||
|
||||
uint8_t io_reg { 0x01 };
|
||||
|
||||
void lcd_rd_assert() {
|
||||
gpio_lcd_rd.set();
|
||||
}
|
||||
|
||||
void lcd_rd_deassert() {
|
||||
gpio_lcd_rd.clear();
|
||||
}
|
||||
|
||||
void lcd_wr_assert() {
|
||||
gpio_lcd_wr.set();
|
||||
}
|
||||
|
||||
void lcd_wr_deassert() {
|
||||
gpio_lcd_wr.clear();
|
||||
}
|
||||
|
||||
void io_stb_assert() {
|
||||
gpio_io_stbx.clear();
|
||||
}
|
||||
|
||||
void io_stb_deassert() {
|
||||
gpio_io_stbx.set();
|
||||
}
|
||||
|
||||
void addr(const bool value) {
|
||||
gpio_addr.write(value);
|
||||
}
|
||||
|
||||
void addr_1() {
|
||||
gpio_addr.set();
|
||||
}
|
||||
|
||||
void addr_0() {
|
||||
gpio_addr.clear();
|
||||
}
|
||||
|
||||
void data_mask_set() {
|
||||
LPC_GPIO->MASK[gpio_data_port_id] = ~gpio_data_mask;
|
||||
}
|
||||
|
||||
void dir_write() {
|
||||
gpio_dir.clear();
|
||||
LPC_GPIO->DIR[gpio_data_port_id] |= gpio_data_mask;
|
||||
/* TODO: Manipulating DIR[3] makes me queasy. The RFFC5072 DATA pin
|
||||
* is also on port 3, and switches direction periodically...
|
||||
* Time to resort to bit-banding to enforce atomicity? But then, how
|
||||
* to change direction on eight bits efficiently? Or do I care, since
|
||||
* the PortaPack data bus shouldn't change direction too frequently?
|
||||
*/
|
||||
}
|
||||
|
||||
void dir_read() {
|
||||
LPC_GPIO->DIR[gpio_data_port_id] &= ~gpio_data_mask;
|
||||
gpio_dir.set();
|
||||
}
|
||||
|
||||
void data_write_low(const uint32_t value) {
|
||||
LPC_GPIO->MPIN[gpio_data_port_id] = (value << gpio_data_shift);
|
||||
}
|
||||
|
||||
void data_write_high(const uint32_t value) {
|
||||
LPC_GPIO->MPIN[gpio_data_port_id] = value;
|
||||
}
|
||||
|
||||
uint32_t data_read() {
|
||||
return (LPC_GPIO->MPIN[gpio_data_port_id] >> gpio_data_shift) & 0xffU;
|
||||
}
|
||||
|
||||
void lcd_command(const uint32_t value) {
|
||||
data_write_high(0); /* Drive high byte (with zero -- don't care) */
|
||||
dir_write(); /* Turn around data bus, MCU->CPLD */
|
||||
addr(0); /* Indicate command */
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
lcd_wr_assert(); /* Latch high byte */
|
||||
|
||||
data_write_low(value); /* Drive low byte (pass-through) */
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
lcd_wr_deassert(); /* Complete write operation */
|
||||
|
||||
addr(1); /* Set up for data phase (most likely after a command) */
|
||||
}
|
||||
|
||||
void lcd_write_data_fast(const uint32_t value) __attribute__((always_inline)) {
|
||||
// NOTE: Assumes and DIR=0 and ADDR=1 from command phase.
|
||||
data_write_high(value); /* Drive high byte */
|
||||
__asm__("nop");
|
||||
lcd_wr_assert(); /* Latch high byte */
|
||||
|
||||
data_write_low(value); /* Drive low byte (pass-through) */
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
lcd_wr_deassert(); /* Complete write operation */
|
||||
}
|
||||
|
||||
uint32_t lcd_read_data_id() {
|
||||
// NOTE: Assumes ADDR=1 from command phase.
|
||||
dir_read();
|
||||
|
||||
/* Start read operation */
|
||||
lcd_rd_assert();
|
||||
/* Wait for passthrough data(15:8) to settle -- ~16ns (3 cycles) typical */
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
const auto value_high = data_read();
|
||||
|
||||
/* Latch data[7:0] */
|
||||
lcd_rd_deassert();
|
||||
/* Wait for latched data[7:0] to settle -- ~26ns (5 cycles) typical */
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
|
||||
const auto value_low = data_read();
|
||||
return (value_high << 8) | value_low;
|
||||
}
|
||||
|
||||
uint32_t lcd_read_data_frame_memory() {
|
||||
// NOTE: Assumes ADDR=1 from command phase.
|
||||
dir_read();
|
||||
|
||||
/* Start read operation */
|
||||
lcd_rd_assert();
|
||||
/* Wait for passthrough data(15:8) to settle -- ~16ns (3 cycles) typical */
|
||||
/* Wait for read control L duration (355ns) */
|
||||
halPolledDelay(71); // 355ns
|
||||
const auto value_high = data_read();
|
||||
|
||||
/* Latch data[7:0] */
|
||||
lcd_rd_deassert();
|
||||
/* Wait for latched data[7:0] to settle -- ~26ns (5 cycles) typical */
|
||||
/* Wait for read control H duration (90ns) */
|
||||
halPolledDelay(18); // 90ns
|
||||
|
||||
const auto value_low = data_read();
|
||||
return (value_high << 8) | value_low;
|
||||
}
|
||||
|
||||
void io_write(const bool address, const uint_fast16_t value) {
|
||||
data_write_low(value);
|
||||
dir_write();
|
||||
addr(address);
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
io_stb_assert();
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
__asm__("nop");
|
||||
io_stb_deassert();
|
||||
}
|
||||
/*
|
||||
void lcd_data_write_command_and_data(
|
||||
const uint_fast16_t command,
|
||||
const uint8_t* const data,
|
||||
const size_t count
|
||||
) {
|
||||
lcd_data_write_command(command);
|
||||
for(size_t i=0; i<count; i++) {
|
||||
lcd_data_write_data(data[i]);
|
||||
}
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
extern IO io;
|
||||
|
||||
} /* namespace portapack */
|
||||
|
||||
#endif/*__PORTAPACK_IO_H__*/
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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 "portapack_shared_memory.hpp"
|
||||
|
||||
SharedMemory& shared_memory = *reinterpret_cast<SharedMemory*>(0x10088000);
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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 __PORTAPACK_SHARED_MEMORY_H__
|
||||
#define __PORTAPACK_SHARED_MEMORY_H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "message_queue.hpp"
|
||||
|
||||
struct TouchADCFrame {
|
||||
uint32_t dr[8];
|
||||
};
|
||||
|
||||
/* NOTE: These structures must be located in the same location in both M4 and M0 binaries */
|
||||
struct SharedMemory {
|
||||
MessageQueue baseband_queue;
|
||||
MessageQueue application_queue;
|
||||
|
||||
// TODO: M0 should directly configure and control DMA channel that is
|
||||
// acquiring ADC samples.
|
||||
TouchADCFrame touch_adc_frame;
|
||||
};
|
||||
|
||||
extern SharedMemory& shared_memory;
|
||||
|
||||
#if defined(LPC43XX_M0)
|
||||
inline void init_message_queues() {
|
||||
new (&shared_memory.baseband_queue) MessageQueue();
|
||||
new (&shared_memory.application_queue) MessageQueue();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif/*__PORTAPACK_SHARED_MEMORY_H__*/
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 "ui.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace ui {
|
||||
|
||||
bool Rect::contains(const Point p) const {
|
||||
return (p.x >= left()) && (p.y >= top()) &&
|
||||
(p.x < right()) && (p.y < bottom());
|
||||
}
|
||||
|
||||
Rect Rect::intersect(const Rect& o) const {
|
||||
const auto x1 = std::max(left(), o.left());
|
||||
const auto x2 = std::min(right(), o.right());
|
||||
const auto y1 = std::max(top(), o.top());
|
||||
const auto y2 = std::min(bottom(), o.bottom());
|
||||
if( (x2 >= x1) && (y2 > y1) ) {
|
||||
return {
|
||||
x1, y1,
|
||||
static_cast<Dim>(x2 - x1), static_cast<Dim>(y2 - y1) };
|
||||
} else {
|
||||
return { };
|
||||
}
|
||||
}
|
||||
|
||||
Rect& Rect::operator+=(const Rect& p) {
|
||||
if( is_empty() ) {
|
||||
*this = p;
|
||||
}
|
||||
if( !p.is_empty() ) {
|
||||
const auto x1 = std::min(left(), p.left());
|
||||
const auto y1 = std::min(top(), p.top());
|
||||
pos = { x1, y1 };
|
||||
const auto x2 = std::max(right(), p.right());
|
||||
const auto y2 = std::max(bottom(), p.bottom());
|
||||
size = { static_cast<Dim>(x2 - x1), static_cast<Dim>(y2 - y1) };
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
||||
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __UI_H__
|
||||
#define __UI_H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace ui {
|
||||
|
||||
using Coord = int16_t;
|
||||
using Dim = int16_t;
|
||||
|
||||
struct Color {
|
||||
uint16_t v;
|
||||
|
||||
constexpr Color(
|
||||
) : v { 0 }
|
||||
{
|
||||
}
|
||||
/*
|
||||
explicit constexpr Color(
|
||||
const uint32_t value
|
||||
) : v { static_cast<uint16_t>(value) }
|
||||
{
|
||||
}
|
||||
*/
|
||||
constexpr Color(
|
||||
uint8_t r,
|
||||
uint8_t g,
|
||||
uint8_t b
|
||||
) : v {
|
||||
static_cast<uint16_t>(
|
||||
((r & 0xf8) << 8)
|
||||
| ((g & 0xfc) << 3)
|
||||
| ((b & 0xf8) >> 3)
|
||||
)}
|
||||
{
|
||||
}
|
||||
|
||||
static constexpr Color black() {
|
||||
return { 0, 0, 0 };
|
||||
}
|
||||
|
||||
static constexpr Color red() {
|
||||
return { 255, 0, 0 };
|
||||
}
|
||||
|
||||
static constexpr Color yellow() {
|
||||
return { 255, 255, 0 };
|
||||
}
|
||||
|
||||
static constexpr Color green() {
|
||||
return { 0, 255, 0 };
|
||||
}
|
||||
|
||||
static constexpr Color blue() {
|
||||
return { 0, 0, 255 };
|
||||
}
|
||||
|
||||
static constexpr Color white() {
|
||||
return { 255, 255, 255 };
|
||||
}
|
||||
};
|
||||
#if 0
|
||||
enum class CardinalDirection : uint8_t {
|
||||
West,
|
||||
South,
|
||||
North,
|
||||
East,
|
||||
};
|
||||
#endif
|
||||
struct Point {
|
||||
Coord x;
|
||||
Coord y;
|
||||
|
||||
constexpr Point(
|
||||
) : x { 0 },
|
||||
y { 0 }
|
||||
{
|
||||
}
|
||||
|
||||
constexpr Point(
|
||||
Coord x,
|
||||
Coord y
|
||||
) : x { x },
|
||||
y { y }
|
||||
{
|
||||
}
|
||||
|
||||
Point operator-() const {
|
||||
return { static_cast<Coord>(-x), static_cast<Coord>(-y) };
|
||||
}
|
||||
|
||||
Point operator+(const Point& p) const {
|
||||
return { static_cast<Coord>(x + p.x), static_cast<Coord>(y + p.y) };
|
||||
}
|
||||
|
||||
Point operator-(const Point& p) const {
|
||||
return { static_cast<Coord>(x - p.x), static_cast<Coord>(y - p.y) };
|
||||
}
|
||||
|
||||
Point& operator+=(const Point& p) {
|
||||
x += p.x;
|
||||
y += p.y;
|
||||
return *this;
|
||||
}
|
||||
#if 0
|
||||
uint32_t magnitude_squared() const {
|
||||
return (x * x) + (y * y);
|
||||
}
|
||||
|
||||
CardinalDirection cardinal_direction() const {
|
||||
/* TODO: Doesn't handle 0,0 */
|
||||
|
||||
const auto rotated = sloppy_rotate_by_45_degrees();
|
||||
|
||||
if( rotated.x > 0 ) {
|
||||
if( rotated.y > 0 ) {
|
||||
return CardinalDirection::East;
|
||||
} else {
|
||||
// y<=0
|
||||
return CardinalDirection::North;
|
||||
}
|
||||
} else {
|
||||
// x<=0
|
||||
if( rotated.y > 0 ) {
|
||||
return CardinalDirection::South;
|
||||
} else {
|
||||
return CardinalDirection::West;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Point sloppy_rotate_by_45_degrees() const {
|
||||
/* Clockwise rotate (in screen coordinates), with a gain in
|
||||
* magnitude of sqrt(2).
|
||||
*/
|
||||
return {
|
||||
static_cast<Coord>(x - y),
|
||||
static_cast<Coord>(x + y)
|
||||
};
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
struct Size {
|
||||
Dim w;
|
||||
Dim h;
|
||||
|
||||
constexpr Size(
|
||||
) : w { 0 },
|
||||
h { 0 }
|
||||
{
|
||||
}
|
||||
|
||||
constexpr Size(
|
||||
Dim w,
|
||||
Dim h
|
||||
) : w { w },
|
||||
h { h }
|
||||
{
|
||||
}
|
||||
|
||||
bool is_empty() const {
|
||||
return (w < 1) || (h < 1);
|
||||
}
|
||||
};
|
||||
|
||||
struct Rect {
|
||||
Point pos;
|
||||
Size size;
|
||||
|
||||
constexpr Rect(
|
||||
) : pos { },
|
||||
size { }
|
||||
{
|
||||
}
|
||||
|
||||
constexpr Rect(
|
||||
Coord x, Coord y,
|
||||
Dim w, Dim h
|
||||
) : pos { x, y },
|
||||
size { w, h }
|
||||
{
|
||||
}
|
||||
|
||||
constexpr Rect(
|
||||
Point pos,
|
||||
Size size
|
||||
) : pos(pos),
|
||||
size(size)
|
||||
{
|
||||
}
|
||||
|
||||
Coord top() const {
|
||||
return pos.y;
|
||||
}
|
||||
|
||||
Coord bottom() const {
|
||||
return pos.y + size.h;
|
||||
}
|
||||
|
||||
Coord left() const {
|
||||
return pos.x;
|
||||
}
|
||||
|
||||
Coord right() const {
|
||||
return pos.x + size.w;
|
||||
}
|
||||
|
||||
Dim width() const {
|
||||
return size.w;
|
||||
}
|
||||
|
||||
Dim height() const {
|
||||
return size.h;
|
||||
}
|
||||
|
||||
Point center() const {
|
||||
return {
|
||||
static_cast<Coord>(pos.x + size.w / 2),
|
||||
static_cast<Coord>(pos.y + size.h / 2)
|
||||
};
|
||||
}
|
||||
|
||||
bool is_empty() const {
|
||||
return size.is_empty();
|
||||
}
|
||||
|
||||
bool contains(const Point p) const;
|
||||
|
||||
Rect intersect(const Rect& o) const;
|
||||
|
||||
Rect operator+(const Point& p) const {
|
||||
return { pos + p, size };
|
||||
}
|
||||
|
||||
Rect& operator+=(const Rect& p);
|
||||
|
||||
operator bool() const {
|
||||
return !size.is_empty();
|
||||
}
|
||||
};
|
||||
|
||||
enum class KeyEvent {
|
||||
/* Ordinals map to bit positions reported by CPLD */
|
||||
Right = 0,
|
||||
Left = 1,
|
||||
Down = 2,
|
||||
Up = 3,
|
||||
Select = 4,
|
||||
};
|
||||
|
||||
using EncoderEvent = int32_t;
|
||||
|
||||
struct TouchEvent {
|
||||
enum class Type : uint32_t {
|
||||
Start = 0,
|
||||
Move = 1,
|
||||
End = 2,
|
||||
};
|
||||
|
||||
Point point;
|
||||
Type type;
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
#endif/*__UI_H__*/
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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 "ui_focus.hpp"
|
||||
#include "ui_widget.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace ui {
|
||||
|
||||
Widget* FocusManager::focus_widget() const {
|
||||
return focus_widget_;
|
||||
}
|
||||
|
||||
void FocusManager::set_focus_widget(Widget* const new_focus_widget) {
|
||||
// Widget already has focus.
|
||||
if( new_focus_widget == focus_widget() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if( new_focus_widget ) {
|
||||
// if( !new_focus_widget->visible() ) {
|
||||
// if( new_focus_widget->hidden() ) {
|
||||
// // New widget is not visible. Do nothing.
|
||||
// // TODO: Should this be a debug assertion?
|
||||
// return;
|
||||
// }
|
||||
if( !new_focus_widget->focusable() ) {
|
||||
// New widget is not focusable. Does it have a preferred child that
|
||||
// can receive focus?
|
||||
set_focus_widget(new_focus_widget->last_child_focus());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Blur old widget.
|
||||
if( focus_widget() ) {
|
||||
focus_widget()->on_blur();
|
||||
focus_widget()->set_dirty();
|
||||
}
|
||||
|
||||
focus_widget_ = new_focus_widget;
|
||||
|
||||
if( focus_widget() ) {
|
||||
focus_widget()->on_focus();
|
||||
focus_widget()->set_dirty();
|
||||
focus_widget()->parent()->set_last_child_focus(focus_widget());
|
||||
}
|
||||
}
|
||||
|
||||
using test_result_t = std::pair<Widget* const, const uint32_t>;
|
||||
using test_fn = std::function<test_result_t(Widget* const)>;
|
||||
using test_collection_t = std::vector<test_result_t>;
|
||||
|
||||
/* Walk all visible widgets in hierarchy, collecting those that pass test */
|
||||
template<typename TestFn>
|
||||
static void widget_collect_visible(Widget* const w, TestFn test, test_collection_t& collection) {
|
||||
for(auto child : w->children()) {
|
||||
if( !child->hidden() ) {
|
||||
const auto result = test(child);
|
||||
if( result.first ) {
|
||||
collection.push_back(result);
|
||||
}
|
||||
widget_collect_visible(child, test, collection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FocusManager::update(
|
||||
Widget* const top_widget,
|
||||
const KeyEvent event
|
||||
) {
|
||||
if( focus_widget() ) {
|
||||
const auto focus_screen_rect = focus_widget()->screen_rect();
|
||||
const auto center = focus_screen_rect.center();
|
||||
|
||||
const auto test_fn = [¢er, event](ui::Widget* const w) -> test_result_t {
|
||||
// if( w->visible() && w->focusable() ) {
|
||||
if( w->focusable() ) {
|
||||
const Point p = w->screen_rect().center() - center;
|
||||
|
||||
/* Heuristic to compute closeness. */
|
||||
/* TODO: Look at metric involving overlap of current
|
||||
* widget rectangle in the direction of movement, with
|
||||
* all the prospective widgets.
|
||||
*/
|
||||
switch(event) {
|
||||
case KeyEvent::Right:
|
||||
if( p.x > 0 ) {
|
||||
return { w, p.x * (abs(p.y) + 1) };
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyEvent::Left:
|
||||
if( p.x < 0 ) {
|
||||
return { w, -p.x * (abs(p.y) + 1) };
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyEvent::Down:
|
||||
if( p.y > 0 ) {
|
||||
return { w, p.y * (abs(p.x) + 1) };
|
||||
}
|
||||
break;
|
||||
|
||||
case KeyEvent::Up:
|
||||
if( p.y < 0 ) {
|
||||
return { w, -p.y * (abs(p.x) + 1) };
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return { nullptr, 0 };
|
||||
};
|
||||
|
||||
test_collection_t collection;
|
||||
widget_collect_visible(top_widget, test_fn, collection);
|
||||
|
||||
const auto compare_fn = [](const test_result_t& a, const test_result_t& b) {
|
||||
return a.second < b.second;
|
||||
};
|
||||
|
||||
const auto nearest = std::min_element(collection.cbegin(), collection.cend(), compare_fn);
|
||||
if( nearest != collection.cend() ) {
|
||||
//focus->blur();
|
||||
const auto new_focus = (*nearest).first;
|
||||
set_focus_widget(new_focus);
|
||||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
void FocusManager::update(
|
||||
Widget* const top_widget,
|
||||
const TouchEvent event
|
||||
) {
|
||||
const auto test_fn = [event](Widget* const w) -> test_result_t {
|
||||
if( w->focusable() ) {
|
||||
const auto r = w->screen_rect();
|
||||
if( r.contains(event) ) {
|
||||
return { w, 0 };
|
||||
}
|
||||
}
|
||||
|
||||
return { nullptr, { } };
|
||||
};
|
||||
|
||||
test_collection_t collection;
|
||||
widget_collect_visible(
|
||||
top_widget, test_fn,
|
||||
collection
|
||||
);
|
||||
|
||||
if( !collection.empty() ) {
|
||||
// Take the last object in the collection, it will be rendered last,
|
||||
// therefore appear "on top".
|
||||
const auto touched = collection.back().first;
|
||||
touched->on_touch(event);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} /* namespace ui */
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2015 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 __UI_FOCUS_H__
|
||||
#define __UI_FOCUS_H__
|
||||
|
||||
#include "ui.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
class Widget;
|
||||
|
||||
class FocusManager {
|
||||
public:
|
||||
Widget* focus_widget() const;
|
||||
void set_focus_widget(Widget* const new_focus_widget);
|
||||
|
||||
void update(Widget* const top_widget, const KeyEvent event);
|
||||
//void update(Widget* const top_widget, const TouchEvent event);
|
||||
|
||||
private:
|
||||
Widget* focus_widget_ { nullptr };
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
#endif/*__UI_FOCUS_H__*/
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 "ui_painter.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
Style Style::invert() const {
|
||||
return {
|
||||
.font = font,
|
||||
.background = foreground,
|
||||
.foreground = background,
|
||||
};
|
||||
}
|
||||
|
||||
size_t Painter::draw_char(const Point p, const Style& style, const char c) {
|
||||
const auto glyph = style.font.glyph(c);
|
||||
display_.draw_glyph(p, glyph, style.foreground, style.background);
|
||||
return glyph.advance().x;
|
||||
}
|
||||
|
||||
size_t Painter::draw_string(Point p, const Style& style, const std::string text) {
|
||||
size_t width = 0;
|
||||
for(const auto c : text) {
|
||||
const auto glyph = style.font.glyph(c);
|
||||
display_.draw_glyph(p, glyph, style.foreground, style.background);
|
||||
const auto advance = glyph.advance();
|
||||
p += advance;
|
||||
width += advance.x;
|
||||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
void Painter::draw_hline(Point p, size_t width, const Color c) {
|
||||
display_.fill_rectangle({ p, { static_cast<Dim>(width), 1 } }, c);
|
||||
}
|
||||
|
||||
void Painter::draw_vline(Point p, size_t height, const Color c) {
|
||||
display_.fill_rectangle({ p, { 1, static_cast<Dim>(height) } }, c);
|
||||
}
|
||||
|
||||
void Painter::draw_rectangle(const Rect r, const Color c) {
|
||||
draw_hline(r.pos, r.size.w, c);
|
||||
draw_vline({ r.pos.x, static_cast<Coord>(r.pos.y + 1) }, r.size.h - 2, c);
|
||||
draw_vline({ static_cast<Coord>(r.pos.x + r.size.w - 1), static_cast<Coord>(r.pos.y + 1) }, r.size.h - 2, c);
|
||||
draw_hline({ r.pos.x, static_cast<Coord>(r.pos.y + r.size.h - 1) }, r.size.w, c);
|
||||
}
|
||||
|
||||
void Painter::fill_rectangle(const Rect r, const Color c) {
|
||||
display_.fill_rectangle(r, c);
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __UI_PAINTER_H__
|
||||
#define __UI_PAINTER_H__
|
||||
|
||||
#include "ui.hpp"
|
||||
#include "ui_text.hpp"
|
||||
|
||||
#include "lcd_ili9341.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace ui {
|
||||
|
||||
struct Style {
|
||||
const Font& font;
|
||||
const Color background;
|
||||
const Color foreground;
|
||||
|
||||
Style invert() const;
|
||||
};
|
||||
|
||||
class Painter {
|
||||
public:
|
||||
Painter(
|
||||
lcd::ILI9341& display
|
||||
) : display_ { display }
|
||||
{
|
||||
}
|
||||
|
||||
Painter(const Painter&) = delete;
|
||||
Painter(Painter&&) = delete;
|
||||
|
||||
size_t draw_char(const Point p, const Style& style, const char c);
|
||||
|
||||
size_t draw_string(Point p, const Style& style, const std::string text);
|
||||
|
||||
void draw_rectangle(const Rect r, const Color c);
|
||||
void fill_rectangle(const Rect r, const Color c);
|
||||
|
||||
private:
|
||||
lcd::ILI9341& display_;
|
||||
|
||||
void draw_hline(Point p, size_t width, const Color c);
|
||||
void draw_vline(Point p, size_t height, const Color c);
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
#endif/*__UI_PAINTER_H__*/
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 "ui_text.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
Glyph Font::glyph(const char c) const {
|
||||
if( c < c_start ) {
|
||||
return { w, h, data };
|
||||
}
|
||||
const size_t index = c - c_start;
|
||||
if( index >= c_count ) {
|
||||
return { w, h, data };
|
||||
} else {
|
||||
return { w, h, &data[index * data_stride] };
|
||||
}
|
||||
}
|
||||
|
||||
Dim Font::line_height() const {
|
||||
return h;
|
||||
}
|
||||
|
||||
Size Font::size_of(const std::string s) const {
|
||||
Size size;
|
||||
|
||||
for(const auto c : s) {
|
||||
const auto glyph_data = glyph(c);
|
||||
size.w += glyph_data.w();
|
||||
size.h = std::max(size.h, glyph_data.h());
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __UI_TEXT_H__
|
||||
#define __UI_TEXT_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
|
||||
#include "ui.hpp"
|
||||
|
||||
namespace ui {
|
||||
|
||||
class Glyph {
|
||||
public:
|
||||
constexpr Glyph(
|
||||
Dim w,
|
||||
Dim h,
|
||||
const uint8_t* const pixels
|
||||
) : w_ { static_cast<uint8_t>(w) },
|
||||
h_ { static_cast<uint8_t>(h) },
|
||||
pixels_ { pixels }
|
||||
{
|
||||
}
|
||||
|
||||
Dim w() const {
|
||||
return w_;
|
||||
}
|
||||
|
||||
Dim h() const {
|
||||
return h_;
|
||||
}
|
||||
|
||||
Size size() const {
|
||||
return { w_, h_ };
|
||||
}
|
||||
|
||||
Point advance() const {
|
||||
return { w_, 0 };
|
||||
}
|
||||
|
||||
const uint8_t* pixels() const {
|
||||
return pixels_;
|
||||
}
|
||||
|
||||
private:
|
||||
const uint8_t w_;
|
||||
const uint8_t h_;
|
||||
const uint8_t* const pixels_;
|
||||
};
|
||||
|
||||
class Font {
|
||||
public:
|
||||
constexpr Font(
|
||||
Dim w,
|
||||
Dim h,
|
||||
const uint8_t* data,
|
||||
char c_start,
|
||||
size_t c_count
|
||||
) : w { w },
|
||||
h { h },
|
||||
data { data },
|
||||
c_start { c_start },
|
||||
c_count { c_count },
|
||||
data_stride { (w * h + 7U) >> 3 }
|
||||
{
|
||||
}
|
||||
|
||||
Glyph glyph(const char c) const;
|
||||
|
||||
Dim line_height() const;
|
||||
Size size_of(const std::string s) const;
|
||||
|
||||
private:
|
||||
const Dim w;
|
||||
const Dim h;
|
||||
const uint8_t* const data;
|
||||
const char c_start;
|
||||
const size_t c_count;
|
||||
const size_t data_stride;
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
#endif/*__UI_TEXT_H__*/
|
||||
@@ -0,0 +1,558 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 "ui_widget.hpp"
|
||||
#include "ui_painter.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <algorithm>
|
||||
|
||||
namespace ui {
|
||||
|
||||
constexpr size_t to_string_max_length = 16;
|
||||
|
||||
static char* to_string_dec_uint_internal(
|
||||
char* p,
|
||||
uint32_t n
|
||||
) {
|
||||
*p = 0;
|
||||
auto q = p;
|
||||
|
||||
do {
|
||||
const uint32_t d = n % 10;
|
||||
const char c = d + 48;
|
||||
*(--q) = c;
|
||||
n /= 10;
|
||||
} while( n != 0 );
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
static char* to_string_dec_uint_pad_internal(
|
||||
char* const term,
|
||||
const uint32_t n,
|
||||
const int32_t l,
|
||||
const char fill
|
||||
) {
|
||||
auto q = to_string_dec_uint_internal(term, n);
|
||||
|
||||
if( fill ) {
|
||||
while( (term - q) < l ) {
|
||||
*(--q) = fill;
|
||||
}
|
||||
}
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
std::string to_string_dec_uint(
|
||||
const uint32_t n,
|
||||
const int32_t l,
|
||||
const char fill
|
||||
) {
|
||||
char p[16];
|
||||
auto term = p + sizeof(p) - 1;
|
||||
auto q = to_string_dec_uint_pad_internal(term, n, l, fill);
|
||||
|
||||
// Right justify.
|
||||
while( (term - q) < l ) {
|
||||
*(--q) = ' ';
|
||||
}
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
std::string to_string_dec_int(
|
||||
const int32_t n,
|
||||
const int32_t l,
|
||||
const char fill
|
||||
) {
|
||||
const size_t negative = (n < 0) ? 1 : 0;
|
||||
uint32_t n_abs = negative ? -n : n;
|
||||
|
||||
char p[16];
|
||||
auto term = p + sizeof(p) - 1;
|
||||
auto q = to_string_dec_uint_pad_internal(term, n_abs, l - negative, fill);
|
||||
|
||||
// Add sign.
|
||||
if( negative ) {
|
||||
*(--q) = '-';
|
||||
}
|
||||
|
||||
// Right justify.
|
||||
while( (term - q) < l ) {
|
||||
*(--q) = ' ';
|
||||
}
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
static void to_string_hex_internal(char* p, const uint32_t n, const int32_t l) {
|
||||
const uint32_t d = n & 0xf;
|
||||
p[l] = (d > 9) ? (d + 87) : (d + 48);
|
||||
if( l > 0 ) {
|
||||
to_string_hex_internal(p, n >> 4, l - 1);
|
||||
}
|
||||
}
|
||||
|
||||
std::string to_string_hex(const uint32_t n, const int32_t l) {
|
||||
char p[16];
|
||||
to_string_hex_internal(p, n, l - 1);
|
||||
p[l] = 0;
|
||||
return p;
|
||||
}
|
||||
|
||||
/* Widget ****************************************************************/
|
||||
|
||||
Point Widget::screen_pos() {
|
||||
return parent() ? (parent()->screen_pos() + parent_rect.pos) : parent_rect.pos;
|
||||
}
|
||||
|
||||
Size Widget::size() const {
|
||||
return parent_rect.size;
|
||||
}
|
||||
|
||||
Rect Widget::screen_rect() {
|
||||
return parent() ? (parent_rect + parent()->screen_pos()) : parent_rect;
|
||||
}
|
||||
|
||||
void Widget::set_parent_rect(const Rect new_parent_rect) {
|
||||
parent_rect = new_parent_rect;
|
||||
set_dirty();
|
||||
}
|
||||
|
||||
Widget* Widget::parent() const {
|
||||
return parent_;
|
||||
}
|
||||
|
||||
void Widget::set_parent(Widget* const widget) {
|
||||
if( parent_ && !widget ) {
|
||||
// We have a parent, but are losing it. Update visible status.
|
||||
visible(false);
|
||||
}
|
||||
|
||||
parent_ = widget;
|
||||
}
|
||||
|
||||
void Widget::set_dirty() {
|
||||
flags.dirty = true;
|
||||
dirty_event();
|
||||
}
|
||||
|
||||
bool Widget::dirty() const {
|
||||
return flags.dirty;
|
||||
}
|
||||
|
||||
void Widget::set_clean() {
|
||||
flags.dirty = false;
|
||||
}
|
||||
|
||||
void Widget::hidden(bool hide) {
|
||||
if( hide != flags.hidden ) {
|
||||
flags.hidden = hide;
|
||||
|
||||
// If parent is hidden, either of these is a no-op.
|
||||
if( hide ) {
|
||||
parent()->set_dirty();
|
||||
/* TODO: Notify self and all non-hidden children that they're
|
||||
* now effectively hidden?
|
||||
*/
|
||||
} else {
|
||||
set_dirty();
|
||||
/* TODO: Notify self and all non-hidden children that they're
|
||||
* now effectively shown?
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::focus() {
|
||||
context().focus_manager.set_focus_widget(this);
|
||||
}
|
||||
|
||||
void Widget::on_focus() {
|
||||
//set_dirty();
|
||||
}
|
||||
|
||||
void Widget::blur() {
|
||||
context().focus_manager.set_focus_widget(nullptr);
|
||||
}
|
||||
|
||||
void Widget::on_blur() {
|
||||
//set_dirty();
|
||||
}
|
||||
|
||||
bool Widget::focusable() const {
|
||||
return flags.focusable;
|
||||
}
|
||||
|
||||
bool Widget::has_focus() {
|
||||
return (context().focus_manager.focus_widget() == this);
|
||||
}
|
||||
|
||||
Widget* Widget::last_child_focus() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Widget::set_last_child_focus(Widget* const child) {
|
||||
// Ignore.
|
||||
(void)child;
|
||||
}
|
||||
|
||||
bool Widget::on_key(const KeyEvent event) {
|
||||
(void)event;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Widget::on_encoder(const EncoderEvent event) {
|
||||
(void)event;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Widget::on_touch(const TouchEvent event) {
|
||||
(void)event;
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::vector<Widget*> Widget::children() const {
|
||||
return { };
|
||||
}
|
||||
|
||||
Context& Widget::context() const {
|
||||
return parent()->context();
|
||||
}
|
||||
|
||||
void Widget::set_style(const Style* new_style) {
|
||||
if( new_style != style_ ) {
|
||||
style_ = new_style;
|
||||
set_dirty();
|
||||
}
|
||||
}
|
||||
|
||||
const Style& Widget::style() const {
|
||||
return style_ ? *style_ : parent()->style();
|
||||
}
|
||||
|
||||
void Widget::visible(bool v) {
|
||||
if( v != flags.visible ) {
|
||||
flags.visible = v;
|
||||
|
||||
/* TODO: This on_show/on_hide implementation seems inelegant.
|
||||
* But I need *some* way to take/configure resources when
|
||||
* a widget becomes visible, and reverse the process when the
|
||||
* widget becomes invisible, whether the widget (or parent) is
|
||||
* hidden, or the widget (or parent) is removed from the tree.
|
||||
*/
|
||||
if( v ) {
|
||||
on_show();
|
||||
} else {
|
||||
on_hide();
|
||||
|
||||
// Set all children invisible too.
|
||||
for(const auto child : children()) {
|
||||
child->visible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* View ******************************************************************/
|
||||
|
||||
void View::set_parent_rect(const Rect new_parent_rect) {
|
||||
Widget::set_parent_rect(new_parent_rect);
|
||||
dirty_screen_rect += screen_rect();
|
||||
}
|
||||
|
||||
void View::paint(Painter& painter) {
|
||||
painter.fill_rectangle(
|
||||
screen_rect(),
|
||||
style().background
|
||||
);
|
||||
}
|
||||
|
||||
void View::add_child(Widget* const widget) {
|
||||
if( widget->parent() == nullptr ) {
|
||||
widget->set_parent(this);
|
||||
children_.push_back(widget);
|
||||
widget->set_dirty();
|
||||
}
|
||||
}
|
||||
|
||||
void View::add_children(const std::vector<Widget*>& children) {
|
||||
for(auto child : children) {
|
||||
add_child(child);
|
||||
}
|
||||
}
|
||||
|
||||
void View::remove_child(Widget* const widget) {
|
||||
children_.erase(std::remove(children_.begin(), children_.end(), widget), children_.end());
|
||||
dirty_screen_rect += widget->screen_rect();
|
||||
widget->set_parent(nullptr);
|
||||
if( dirty_screen_rect ) {
|
||||
set_dirty();
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<Widget*> View::children() const {
|
||||
return children_;
|
||||
}
|
||||
|
||||
Widget* View::initial_focus() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Rectangle *************************************************************/
|
||||
|
||||
void Rectangle::set_color(const Color c) {
|
||||
color = c;
|
||||
set_dirty();
|
||||
}
|
||||
|
||||
void Rectangle::paint(Painter& painter) {
|
||||
painter.fill_rectangle(
|
||||
screen_rect(),
|
||||
color
|
||||
);
|
||||
}
|
||||
|
||||
/* Text ******************************************************************/
|
||||
|
||||
void Text::set(const std::string value) {
|
||||
text = value;
|
||||
set_dirty();
|
||||
}
|
||||
|
||||
void Text::paint(Painter& painter) {
|
||||
painter.draw_string(
|
||||
screen_pos(),
|
||||
style(),
|
||||
text
|
||||
);
|
||||
}
|
||||
|
||||
/* Button ****************************************************************/
|
||||
|
||||
void Button::set_text(const std::string value) {
|
||||
text_ = value;
|
||||
set_dirty();
|
||||
}
|
||||
|
||||
std::string Button::text() const {
|
||||
return text_;
|
||||
}
|
||||
|
||||
void Button::paint(Painter& painter) {
|
||||
const auto r = screen_rect();
|
||||
|
||||
const auto paint_style = (has_focus() || flags.highlighted) ? style().invert() : style();
|
||||
|
||||
painter.draw_rectangle(r, style().foreground);
|
||||
|
||||
painter.fill_rectangle(
|
||||
{
|
||||
static_cast<Coord>(r.pos.x + 1), static_cast<Coord>(r.pos.y + 1),
|
||||
static_cast<Dim>(r.size.w - 2), static_cast<Dim>(r.size.h - 2)
|
||||
},
|
||||
paint_style.background
|
||||
);
|
||||
|
||||
const auto label_r = paint_style.font.size_of(text_);
|
||||
painter.draw_string(
|
||||
{
|
||||
static_cast<Coord>(r.pos.x + (r.size.w - label_r.w) / 2),
|
||||
static_cast<Coord>(r.pos.y + (r.size.h - label_r.h) / 2)
|
||||
},
|
||||
paint_style,
|
||||
text_
|
||||
);
|
||||
}
|
||||
|
||||
bool Button::on_key(const KeyEvent key) {
|
||||
if( key == KeyEvent::Select ) {
|
||||
if( on_select ) {
|
||||
on_select(*this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Button::on_touch(const TouchEvent event) {
|
||||
switch(event.type) {
|
||||
case TouchEvent::Type::Start:
|
||||
flags.highlighted = true;
|
||||
set_dirty();
|
||||
return true;
|
||||
|
||||
|
||||
case TouchEvent::Type::End:
|
||||
flags.highlighted = false;
|
||||
set_dirty();
|
||||
if( on_select ) {
|
||||
on_select(*this);
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
#if 0
|
||||
switch(event.type) {
|
||||
case TouchEvent::Type::Start:
|
||||
flags.highlighted = true;
|
||||
set_dirty();
|
||||
return true;
|
||||
|
||||
case TouchEvent::Type::Move:
|
||||
{
|
||||
const bool new_highlighted = screen_rect().contains(event.point);
|
||||
if( flags.highlighted != new_highlighted ) {
|
||||
flags.highlighted = new_highlighted;
|
||||
set_dirty();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
case TouchEvent::Type::End:
|
||||
if( flags.highlighted ) {
|
||||
flags.highlighted = false;
|
||||
set_dirty();
|
||||
if( on_select ) {
|
||||
on_select(*this);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* OptionsField **********************************************************/
|
||||
|
||||
size_t OptionsField::selected_index() const {
|
||||
return selected_index_;
|
||||
}
|
||||
|
||||
void OptionsField::set_selected_index(const size_t new_index) {
|
||||
if( new_index < options.size() ) {
|
||||
if( new_index != selected_index() ) {
|
||||
selected_index_ = new_index;
|
||||
if( on_change ) {
|
||||
on_change(selected_index(), options[selected_index()].second);
|
||||
}
|
||||
set_dirty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OptionsField::set_by_value(value_t v) {
|
||||
size_t new_index { 0 };
|
||||
for(const auto& option : options) {
|
||||
if( option.second >= v ) {
|
||||
set_selected_index(new_index);
|
||||
break;
|
||||
}
|
||||
new_index++;
|
||||
}
|
||||
}
|
||||
|
||||
void OptionsField::paint(Painter& painter) {
|
||||
const auto paint_style = has_focus() ? style().invert() : style();
|
||||
|
||||
if( selected_index() < options.size() ) {
|
||||
const auto text = options[selected_index()].first;
|
||||
painter.draw_string(
|
||||
screen_pos(),
|
||||
paint_style,
|
||||
text
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
bool OptionsField::on_encoder(const EncoderEvent delta) {
|
||||
set_selected_index(selected_index() + delta);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OptionsField::on_touch(const TouchEvent event) {
|
||||
if( event.type == TouchEvent::Type::Start ) {
|
||||
focus();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* NumberField ***********************************************************/
|
||||
|
||||
int32_t NumberField::value() const {
|
||||
return value_;
|
||||
}
|
||||
|
||||
void NumberField::set_value(int32_t new_value) {
|
||||
new_value = clip_value(new_value);
|
||||
|
||||
if( new_value != value() ) {
|
||||
value_ = new_value;
|
||||
if( on_change ) {
|
||||
on_change(value_);
|
||||
}
|
||||
set_dirty();
|
||||
}
|
||||
}
|
||||
|
||||
void NumberField::paint(Painter& painter) {
|
||||
const auto text = to_string_dec_int(value_, length_, fill_char);
|
||||
|
||||
const auto paint_style = has_focus() ? style().invert() : style();
|
||||
|
||||
painter.draw_string(
|
||||
screen_pos(),
|
||||
paint_style,
|
||||
text
|
||||
);
|
||||
}
|
||||
|
||||
bool NumberField::on_encoder(const EncoderEvent delta) {
|
||||
set_value(value() + (delta * step));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NumberField::on_touch(const TouchEvent event) {
|
||||
if( event.type == TouchEvent::Type::Start ) {
|
||||
focus();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t NumberField::clip_value(int32_t value) {
|
||||
if( value > range.second ) {
|
||||
value = range.second;
|
||||
}
|
||||
if( value < range.first ) {
|
||||
value = range.first;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
} /* namespace ui */
|
||||
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __UI_WIDGET_H__
|
||||
#define __UI_WIDGET_H__
|
||||
|
||||
#include "ui.hpp"
|
||||
#include "ui_text.hpp"
|
||||
#include "ui_painter.hpp"
|
||||
#include "ui_focus.hpp"
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
#include "lcd_ili9341.hpp"
|
||||
#include "message.hpp"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace ui {
|
||||
|
||||
extern void dirty_event();
|
||||
|
||||
std::string to_string_dec_uint(const uint32_t n, const int32_t l, const char fill = 0);
|
||||
std::string to_string_dec_int(const int32_t n, const int32_t l, const char fill = 0);
|
||||
std::string to_string_hex(const uint32_t n, const int32_t l);
|
||||
|
||||
struct Context {
|
||||
FocusManager focus_manager;
|
||||
lcd::ILI9341 display;
|
||||
MessageHandlerMap message_map;
|
||||
};
|
||||
|
||||
class Widget {
|
||||
public:
|
||||
constexpr Widget(
|
||||
) : parent_rect { }
|
||||
{
|
||||
}
|
||||
|
||||
constexpr Widget(
|
||||
Rect parent_rect
|
||||
) : parent_rect { parent_rect }
|
||||
{
|
||||
}
|
||||
|
||||
Widget(const Widget&) = delete;
|
||||
Widget(Widget&&) = delete;
|
||||
|
||||
virtual ~Widget() = default;
|
||||
|
||||
Point screen_pos();
|
||||
Size size() const;
|
||||
Rect screen_rect();
|
||||
virtual void set_parent_rect(const Rect new_parent_rect);
|
||||
|
||||
Widget* parent() const;
|
||||
void set_parent(Widget* const widget);
|
||||
|
||||
bool hidden() const { return flags.hidden; }
|
||||
void hidden(bool hide);
|
||||
|
||||
virtual void focus();
|
||||
virtual void on_focus();
|
||||
virtual void blur();
|
||||
virtual void on_blur();
|
||||
bool focusable() const;
|
||||
bool has_focus();
|
||||
virtual Widget* last_child_focus() const;
|
||||
virtual void set_last_child_focus(Widget* const child);
|
||||
|
||||
virtual void paint(Painter& painter) = 0;
|
||||
|
||||
virtual void on_show() { };
|
||||
virtual void on_hide() { };
|
||||
|
||||
virtual bool on_key(const KeyEvent event);
|
||||
virtual bool on_encoder(const EncoderEvent event);
|
||||
virtual bool on_touch(const TouchEvent event);
|
||||
virtual const std::vector<Widget*> children() const;
|
||||
|
||||
virtual Context& context() const;
|
||||
|
||||
void set_style(const Style* new_style);
|
||||
|
||||
const Style& style() const;
|
||||
|
||||
// State management methods.
|
||||
void set_dirty();
|
||||
bool dirty() const;
|
||||
void set_clean();
|
||||
|
||||
void visible(bool v);
|
||||
|
||||
protected:
|
||||
/* Widget rectangle relative to parent pos(). */
|
||||
Rect parent_rect;
|
||||
const Style* style_ { nullptr };
|
||||
Widget* parent_ { nullptr };
|
||||
|
||||
struct flags_t {
|
||||
bool dirty : 1; // Widget content has changed.
|
||||
bool hidden : 1; // Hide widget and children.
|
||||
bool focusable : 1; // Widget can receive focus.
|
||||
bool highlighted : 1; // Show in a highlighted style.
|
||||
bool visible : 1; // Object was visible during last paint.
|
||||
};
|
||||
|
||||
flags_t flags {
|
||||
.dirty = true,
|
||||
.hidden = false,
|
||||
.focusable = false,
|
||||
.highlighted = false,
|
||||
.visible = false,
|
||||
};
|
||||
};
|
||||
|
||||
class View : public Widget {
|
||||
public:
|
||||
View() {
|
||||
}
|
||||
|
||||
View(Rect parent_rect) {
|
||||
set_parent_rect(parent_rect);
|
||||
}
|
||||
|
||||
// TODO: ~View() should on_hide() all children?
|
||||
|
||||
void set_parent_rect(const Rect new_parent_rect) override;
|
||||
|
||||
void paint(Painter& painter) override;
|
||||
|
||||
void add_child(Widget* const widget);
|
||||
void add_children(const std::vector<Widget*>& children);
|
||||
void remove_child(Widget* const widget);
|
||||
const std::vector<Widget*> children() const override;
|
||||
|
||||
virtual Widget* initial_focus();
|
||||
|
||||
protected:
|
||||
std::vector<Widget*> children_;
|
||||
Rect dirty_screen_rect;
|
||||
|
||||
void invalidate_child(Widget* const widget);
|
||||
};
|
||||
|
||||
class Rectangle : public Widget {
|
||||
public:
|
||||
constexpr Rectangle(
|
||||
const Rect parent_rect,
|
||||
const Color c
|
||||
) : Widget { parent_rect },
|
||||
color { c }
|
||||
{
|
||||
}
|
||||
|
||||
void paint(Painter& painter) override;
|
||||
|
||||
void set_color(const Color c);
|
||||
|
||||
private:
|
||||
Color color;
|
||||
};
|
||||
|
||||
class Text : public Widget {
|
||||
public:
|
||||
Text(
|
||||
) : text { "" } {
|
||||
}
|
||||
|
||||
Text(
|
||||
Rect parent_rect,
|
||||
std::string text
|
||||
) : Widget { parent_rect },
|
||||
text { text }
|
||||
{
|
||||
}
|
||||
|
||||
Text(
|
||||
Rect parent_rect
|
||||
) : Text { parent_rect, { } }
|
||||
{
|
||||
}
|
||||
|
||||
void set(const std::string value);
|
||||
|
||||
void paint(Painter& painter) override;
|
||||
|
||||
private:
|
||||
std::string text;
|
||||
};
|
||||
|
||||
class Button : public Widget {
|
||||
public:
|
||||
std::function<void(Button&)> on_select;
|
||||
|
||||
Button(
|
||||
Rect parent_rect,
|
||||
std::string text
|
||||
) : Widget { parent_rect },
|
||||
text_ { text }
|
||||
{
|
||||
flags.focusable = true;
|
||||
}
|
||||
|
||||
Button(
|
||||
) : Button { { }, { } }
|
||||
{
|
||||
}
|
||||
|
||||
void set_text(const std::string value);
|
||||
std::string text() const;
|
||||
|
||||
void paint(Painter& painter) override;
|
||||
|
||||
bool on_key(const KeyEvent key) override;
|
||||
bool on_touch(const TouchEvent event) override;
|
||||
|
||||
private:
|
||||
std::string text_;
|
||||
};
|
||||
|
||||
class OptionsField : public Widget {
|
||||
public:
|
||||
using name_t = std::string;
|
||||
using value_t = int32_t;
|
||||
using option_t = std::pair<name_t, value_t>;
|
||||
using options_t = std::vector<option_t>;
|
||||
|
||||
std::function<void(size_t, value_t)> on_change;
|
||||
|
||||
OptionsField(
|
||||
Point parent_pos,
|
||||
size_t length,
|
||||
options_t options
|
||||
) : Widget { { parent_pos, { static_cast<ui::Dim>(8 * length), 16 } } },
|
||||
length_ { length },
|
||||
options { options }
|
||||
{
|
||||
flags.focusable = true;
|
||||
}
|
||||
|
||||
size_t selected_index() const;
|
||||
void set_selected_index(const size_t new_index);
|
||||
|
||||
void set_by_value(value_t v);
|
||||
|
||||
void paint(Painter& painter) override;
|
||||
|
||||
bool on_encoder(const EncoderEvent delta) override;
|
||||
bool on_touch(const TouchEvent event) override;
|
||||
|
||||
private:
|
||||
const size_t length_;
|
||||
options_t options;
|
||||
size_t selected_index_ { 0 };
|
||||
};
|
||||
|
||||
class NumberField : public Widget {
|
||||
public:
|
||||
std::function<void(int32_t)> on_change;
|
||||
|
||||
using range_t = std::pair<int32_t, int32_t>;
|
||||
|
||||
NumberField(
|
||||
Point parent_pos,
|
||||
size_t length,
|
||||
range_t range,
|
||||
int32_t step,
|
||||
char fill_char
|
||||
) : Widget { { parent_pos, { static_cast<ui::Dim>(8 * length), 16 } } },
|
||||
range { range },
|
||||
step { step },
|
||||
length_ { length },
|
||||
fill_char { fill_char }
|
||||
{
|
||||
flags.focusable = true;
|
||||
}
|
||||
|
||||
NumberField(const NumberField&) = delete;
|
||||
NumberField(NumberField&&) = delete;
|
||||
|
||||
int32_t value() const;
|
||||
void set_value(int32_t new_value);
|
||||
|
||||
void paint(Painter& painter) override;
|
||||
|
||||
bool on_encoder(const EncoderEvent delta) override;
|
||||
bool on_touch(const TouchEvent event) override;
|
||||
|
||||
private:
|
||||
const range_t range;
|
||||
const int32_t step;
|
||||
const size_t length_;
|
||||
const char fill_char;
|
||||
int32_t value_;
|
||||
|
||||
int32_t clip_value(int32_t value);
|
||||
};
|
||||
|
||||
} /* namespace ui */
|
||||
|
||||
#endif/*__UI_WIDGET_H__*/
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 <ch.h>
|
||||
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#if 0
|
||||
uint32_t gcd(const uint32_t u, const uint32_t v) {
|
||||
/* From http://en.wikipedia.org/wiki/Binary_GCD_algorithm */
|
||||
|
||||
if( u == v ) {
|
||||
return u;
|
||||
}
|
||||
|
||||
if( u == 0 ) {
|
||||
return v;
|
||||
}
|
||||
|
||||
if( v == 0 ) {
|
||||
return u;
|
||||
}
|
||||
|
||||
if( ~u & 1 ) {
|
||||
if( v & 1 ) {
|
||||
return gcd(u >> 1, v);
|
||||
} else {
|
||||
return gcd(u >> 1, v >> 1) << 1;
|
||||
}
|
||||
}
|
||||
|
||||
if( ~v & 1 ) {
|
||||
return gcd(u, v >> 1);
|
||||
}
|
||||
|
||||
if( u > v ) {
|
||||
return gcd((u - v) >> 1, v);
|
||||
}
|
||||
|
||||
return gcd((v - u) >> 1, u);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* GCD implementation derived from recursive implementation at
|
||||
* http://en.wikipedia.org/wiki/Binary_GCD_algorithm
|
||||
*/
|
||||
|
||||
static constexpr uint32_t gcd_top(const uint32_t u, const uint32_t v);
|
||||
|
||||
static constexpr uint32_t gcd_larger(const uint32_t u, const uint32_t v) {
|
||||
return (u > v) ? gcd_top((u - v) >> 1, v) : gcd_top((v - u) >> 1, u);
|
||||
}
|
||||
|
||||
static constexpr uint32_t gcd_u_odd_v_even(const uint32_t u, const uint32_t v) {
|
||||
return (~v & 1) ? gcd_top(u, v >> 1) : gcd_larger(u, v);
|
||||
}
|
||||
|
||||
static constexpr uint32_t gcd_v_odd(const uint32_t u, const uint32_t v) {
|
||||
return (v & 1)
|
||||
? gcd_top(u >> 1, v)
|
||||
: (gcd_top(u >> 1, v >> 1) << 1);
|
||||
}
|
||||
|
||||
static constexpr uint32_t gcd_u_even(const uint32_t u, const uint32_t v) {
|
||||
return (~u & 1)
|
||||
? gcd_v_odd(u, v)
|
||||
: gcd_u_odd_v_even(u, v)
|
||||
;
|
||||
}
|
||||
|
||||
static constexpr uint32_t gcd_v_zero(const uint32_t u, const uint32_t v) {
|
||||
return (v == 0) ? u : gcd_u_even(u, v);
|
||||
}
|
||||
|
||||
static constexpr uint32_t gcd_u_zero(const uint32_t u, const uint32_t v) {
|
||||
return (u == 0) ? v : gcd_v_zero(u, v);
|
||||
}
|
||||
|
||||
static constexpr uint32_t gcd_uv_equal(const uint32_t u, const uint32_t v) {
|
||||
return (u == v) ? u : gcd_u_zero(u, v);
|
||||
}
|
||||
|
||||
static constexpr uint32_t gcd_top(const uint32_t u, const uint32_t v) {
|
||||
return gcd_uv_equal(u, v);
|
||||
}
|
||||
|
||||
uint32_t gcd(const uint32_t u, const uint32_t v) {
|
||||
return gcd_top(u, v);
|
||||
}
|
||||
|
||||
/* Memory management, overriding toolchain new, which uses malloc */
|
||||
/* TODO: Move to something like "memory.cpp"! Not utility.cpp. */
|
||||
|
||||
void* operator new(size_t size) {
|
||||
return chHeapAlloc(0x0, size);
|
||||
}
|
||||
|
||||
void* operator new[](size_t size) {
|
||||
return chHeapAlloc(0x0, size);
|
||||
}
|
||||
|
||||
void operator delete(void* p) noexcept {
|
||||
chHeapFree(p);
|
||||
}
|
||||
|
||||
void operator delete[](void* p) noexcept {
|
||||
chHeapFree(p);
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __UTILITY_H__
|
||||
#define __UTILITY_H__
|
||||
|
||||
#include <type_traits>
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
|
||||
#include <hal.h>
|
||||
|
||||
#define LOCATE_IN_RAM __attribute__((section(".ramtext")))
|
||||
|
||||
template<typename E>
|
||||
constexpr typename std::underlying_type<E>::type toUType(E enumerator) noexcept {
|
||||
/* Thanks, Scott Meyers! */
|
||||
return static_cast<typename std::underlying_type<E>::type>(enumerator);
|
||||
}
|
||||
|
||||
inline uint32_t flp2(uint32_t v) {
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
return v - (v >> 1);
|
||||
}
|
||||
|
||||
uint32_t gcd(const uint32_t u, const uint32_t v);
|
||||
|
||||
template<class T>
|
||||
inline constexpr T pow(const T base, unsigned const exponent) {
|
||||
return (exponent == 0) ? 1 : (base * pow(base, exponent - 1));
|
||||
}
|
||||
|
||||
#if defined(LPC43XX_M4)
|
||||
static inline bool m4_flag_saturation() {
|
||||
return __get_APSR() & (1U << 27);
|
||||
}
|
||||
|
||||
static inline void clear_m4_flag_saturation() {
|
||||
uint32_t flags = 1;
|
||||
__asm volatile ("MSR APSR_nzcvqg, %0" : : "r" (flags));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Override new/delete to use Chibi/OS heap functions */
|
||||
/* NOTE: Do not inline these, it doesn't work. ;-) */
|
||||
void* operator new(size_t size);
|
||||
void* operator new[](size_t size);
|
||||
void operator delete(void* p);
|
||||
void operator delete[](void* p);
|
||||
|
||||
namespace std {
|
||||
|
||||
/*! Stephan T Lavavej (STL!) implementation of make_unique, which has been accepted into the C++14 standard.
|
||||
* It includes handling for arrays.
|
||||
* Paper here: http://isocpp.org/files/papers/N3656.txt
|
||||
*/
|
||||
template<class T> struct _Unique_if {
|
||||
typedef unique_ptr<T> _Single_object;
|
||||
};
|
||||
|
||||
//! Specialization for unbound array
|
||||
template<class T> struct _Unique_if<T[]> {
|
||||
typedef unique_ptr<T[]> _Unknown_bound;
|
||||
};
|
||||
|
||||
//! Specialization for array of known size
|
||||
template<class T, size_t N> struct _Unique_if<T[N]> {
|
||||
typedef void _Known_bound;
|
||||
};
|
||||
|
||||
//! Specialization for normal object type
|
||||
template<class T, class... Args>
|
||||
typename _Unique_if<T>::_Single_object
|
||||
make_unique(Args&& ... args) {
|
||||
return unique_ptr<T>(new T(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
//! Specialization for unknown bound
|
||||
template<class T>
|
||||
typename _Unique_if<T>::_Unknown_bound
|
||||
make_unique(size_t n) {
|
||||
typedef typename remove_extent<T>::type U;
|
||||
return unique_ptr<T>(new U[n]());
|
||||
}
|
||||
|
||||
//! Deleted specialization
|
||||
template<class T, class... Args>
|
||||
typename _Unique_if<T>::_Known_bound
|
||||
make_unique(Args&& ...) = delete;
|
||||
|
||||
} /* namespace std */
|
||||
|
||||
#endif/*__UTILITY_H__*/
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 Fvoranklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __VOLUME_H__
|
||||
#define __VOLUME_H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class volume_t {
|
||||
public:
|
||||
constexpr volume_t operator-() const {
|
||||
return { .cb = -cb };
|
||||
}
|
||||
|
||||
constexpr volume_t operator+(const volume_t& other) const {
|
||||
return { .cb = cb + other.cb };
|
||||
}
|
||||
|
||||
constexpr volume_t operator-(const volume_t& other) const {
|
||||
return { .cb = cb - other.cb };
|
||||
}
|
||||
|
||||
volume_t& operator+=(const volume_t& other) {
|
||||
cb += other.cb;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr bool operator<(const volume_t& other) const {
|
||||
return cb < other.cb;
|
||||
}
|
||||
|
||||
constexpr bool operator>(const volume_t& other) const {
|
||||
return cb > other.cb;
|
||||
}
|
||||
|
||||
static constexpr volume_t centibel(const int cb) {
|
||||
return { .cb = cb };
|
||||
}
|
||||
|
||||
static constexpr volume_t decibel(const int db) {
|
||||
return { .cb = db * 10 };
|
||||
}
|
||||
|
||||
int32_t centibel() const {
|
||||
return cb;
|
||||
}
|
||||
|
||||
int32_t decibel() const {
|
||||
return cb / 10;
|
||||
}
|
||||
|
||||
private:
|
||||
int32_t cb;
|
||||
|
||||
constexpr volume_t(
|
||||
const int cb
|
||||
) : cb(cb)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
constexpr volume_t operator"" _cB(long double v) {
|
||||
return volume_t::centibel(v);
|
||||
}
|
||||
|
||||
constexpr volume_t operator"" _dB(long double v) {
|
||||
return volume_t::centibel(v * 10);
|
||||
}
|
||||
|
||||
struct volume_range_t {
|
||||
volume_t min;
|
||||
volume_t max;
|
||||
|
||||
volume_t limit(const volume_t value) const {
|
||||
if( value < min ) {
|
||||
return min;
|
||||
}
|
||||
if( value > max ) {
|
||||
return max;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
volume_t normalize(const volume_t value) const {
|
||||
/* Limit volume to specified range, and adjust minimum value to 0. */
|
||||
return limit(value) - min;
|
||||
}
|
||||
};
|
||||
|
||||
#endif/*__VOLUME_H__*/
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 <cstdint>
|
||||
#include <array>
|
||||
|
||||
#include "wm8731.hpp"
|
||||
|
||||
namespace wolfson {
|
||||
namespace wm8731 {
|
||||
|
||||
void WM8731::write(const address_t reg_address, const reg_t value) {
|
||||
const uint16_t word = (reg_address << 9) | value;
|
||||
const std::array<uint8_t, 2> values {
|
||||
static_cast<uint8_t>(word >> 8),
|
||||
static_cast<uint8_t>(word & 0xff),
|
||||
};
|
||||
bus.transmit(bus_address, values.data(), values.size());
|
||||
}
|
||||
|
||||
} /* namespace wm8731 */
|
||||
} /* namespace wolfson */
|
||||
@@ -0,0 +1,462 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 __WM8731_H__
|
||||
#define __WM8731_H__
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "i2c_pp.hpp"
|
||||
#include "wm8731.hpp"
|
||||
|
||||
#include "utility.hpp"
|
||||
#include "volume.hpp"
|
||||
|
||||
namespace wolfson {
|
||||
namespace wm8731 {
|
||||
|
||||
constexpr volume_range_t headphone_gain_range { -121.0_dB, 6.0_dB };
|
||||
constexpr volume_range_t line_in_gain_range { -34.5_dB, 12.0_dB };
|
||||
|
||||
enum class ADCSource {
|
||||
Line = 0,
|
||||
Microphone = 1,
|
||||
};
|
||||
|
||||
using address_t = uint8_t;
|
||||
using reg_t = uint16_t;
|
||||
|
||||
constexpr size_t reg_count = 10;
|
||||
|
||||
enum class Register : address_t {
|
||||
LeftLineIn = 0x00,
|
||||
RightLineIn = 0x01,
|
||||
LeftHeadphoneOut = 0x02,
|
||||
RightHeadphoneOut = 0x03,
|
||||
AnalogAudioPathControl = 0x04,
|
||||
DigitalAudioPathControl = 0x05,
|
||||
PowerDownControl = 0x06,
|
||||
DigitalAudioInterfaceFormat = 0x07,
|
||||
SamplingControl = 0x08,
|
||||
ActiveControl = 0x09,
|
||||
};
|
||||
|
||||
struct LeftLineIn {
|
||||
reg_t linvol : 5;
|
||||
reg_t reserved0 : 2;
|
||||
reg_t linmute : 1;
|
||||
reg_t lrinboth : 1;
|
||||
reg_t reserved1 : 7;
|
||||
};
|
||||
|
||||
static_assert(sizeof(LeftLineIn) == sizeof(reg_t), "LeftLineIn type wrong size");
|
||||
|
||||
struct RightLineIn {
|
||||
reg_t rinvol : 5;
|
||||
reg_t reserved0 : 2;
|
||||
reg_t rinmute : 1;
|
||||
reg_t rlinboth : 1;
|
||||
reg_t reserved1 : 7;
|
||||
};
|
||||
|
||||
static_assert(sizeof(RightLineIn) == sizeof(reg_t), "RightLineIn type wrong size");
|
||||
|
||||
struct LeftHeadphoneOut {
|
||||
reg_t lhpvol : 7;
|
||||
reg_t lzcen : 1;
|
||||
reg_t lrhpboth : 1;
|
||||
reg_t reserved0 : 7;
|
||||
};
|
||||
|
||||
static_assert(sizeof(LeftHeadphoneOut) == sizeof(reg_t), "LeftHeadphoneOut type wrong size");
|
||||
|
||||
struct RightHeadphoneOut {
|
||||
reg_t rhpvol : 7;
|
||||
reg_t rzcen : 1;
|
||||
reg_t rlhpboth : 1;
|
||||
reg_t reserved0 : 7;
|
||||
};
|
||||
|
||||
static_assert(sizeof(RightHeadphoneOut) == sizeof(reg_t), "RightHeadphoneOut type wrong size");
|
||||
|
||||
struct AnalogAudioPathControl {
|
||||
reg_t micboost : 1;
|
||||
reg_t mutemic : 1;
|
||||
reg_t insel : 1;
|
||||
reg_t bypass : 1;
|
||||
reg_t dacsel : 1;
|
||||
reg_t sidetone : 1;
|
||||
reg_t sideatt : 2;
|
||||
reg_t reserved0 : 8;
|
||||
};
|
||||
|
||||
static_assert(sizeof(AnalogAudioPathControl) == sizeof(reg_t), "AnalogAudioPathControl type wrong size");
|
||||
|
||||
struct DigitalAudioPathControl {
|
||||
reg_t adchpd : 1;
|
||||
reg_t deemp : 2;
|
||||
reg_t dacmu : 1;
|
||||
reg_t hpor : 1;
|
||||
reg_t reserved0 : 11;
|
||||
};
|
||||
|
||||
static_assert(sizeof(DigitalAudioPathControl) == sizeof(reg_t), "DigitalAudioPathControl type wrong size");
|
||||
|
||||
struct PowerDownControl {
|
||||
reg_t lineinpd : 1;
|
||||
reg_t micpd : 1;
|
||||
reg_t adcpd : 1;
|
||||
reg_t dacpd : 1;
|
||||
reg_t outpd : 1;
|
||||
reg_t oscpd : 1;
|
||||
reg_t clkoutpd : 1;
|
||||
reg_t poweroff : 1;
|
||||
reg_t reserved0 : 8;
|
||||
};
|
||||
|
||||
static_assert(sizeof(PowerDownControl) == sizeof(reg_t), "PowerDownControl type wrong size");
|
||||
|
||||
struct DigitalAudioInterfaceFormat {
|
||||
reg_t format : 2;
|
||||
reg_t iwl : 2;
|
||||
reg_t lrp : 1;
|
||||
reg_t lrswap : 1;
|
||||
reg_t ms : 1;
|
||||
reg_t bclkinv : 1;
|
||||
reg_t reserved0 : 8;
|
||||
};
|
||||
|
||||
static_assert(sizeof(DigitalAudioInterfaceFormat) == sizeof(reg_t), "DigitalAudioInterfaceFormat type wrong size");
|
||||
|
||||
struct SamplingControl {
|
||||
reg_t usb_normal : 1;
|
||||
reg_t bosr : 1;
|
||||
reg_t sr : 4;
|
||||
reg_t clkidiv2 : 1;
|
||||
reg_t clkodiv2 : 1;
|
||||
reg_t reserved0 : 8;
|
||||
};
|
||||
|
||||
static_assert(sizeof(SamplingControl) == sizeof(reg_t), "SamplingControl type wrong size");
|
||||
|
||||
struct ActiveControl {
|
||||
reg_t active : 1;
|
||||
reg_t reserved0 : 15;
|
||||
};
|
||||
|
||||
static_assert(sizeof(ActiveControl) == sizeof(reg_t), "ActiveControl type wrong size");
|
||||
|
||||
struct Reset {
|
||||
reg_t reset : 9;
|
||||
reg_t reserved0 : 7;
|
||||
};
|
||||
|
||||
static_assert(sizeof(Reset) == sizeof(reg_t), "Reset type wrong size");
|
||||
|
||||
struct Register_Type {
|
||||
LeftLineIn left_line_in;
|
||||
RightLineIn right_line_in;
|
||||
LeftHeadphoneOut left_headphone_out;
|
||||
RightHeadphoneOut right_headphone_out;
|
||||
AnalogAudioPathControl analog_audio_path_control;
|
||||
DigitalAudioPathControl digital_audio_path_control;
|
||||
PowerDownControl power_down_control;
|
||||
DigitalAudioInterfaceFormat digital_audio_interface_format;
|
||||
SamplingControl sampling_control;
|
||||
ActiveControl active_control;
|
||||
};
|
||||
|
||||
static_assert(sizeof(Register_Type) == reg_count * sizeof(reg_t), "Register_Type wrong size");
|
||||
|
||||
struct RegisterMap {
|
||||
constexpr RegisterMap(
|
||||
Register_Type values
|
||||
) : r(values)
|
||||
{
|
||||
}
|
||||
|
||||
union {
|
||||
Register_Type r;
|
||||
std::array<reg_t, reg_count> w;
|
||||
};
|
||||
};
|
||||
|
||||
static_assert(sizeof(RegisterMap) == reg_count * sizeof(reg_t), "RegisterMap type wrong size");
|
||||
|
||||
constexpr RegisterMap default_after_reset { Register_Type {
|
||||
.left_line_in = {
|
||||
.linvol = 0b10111,
|
||||
.reserved0 = 0b00,
|
||||
.linmute = 0b1,
|
||||
.lrinboth = 0b0,
|
||||
.reserved1 = 0,
|
||||
},
|
||||
.right_line_in = {
|
||||
.rinvol = 0b10111,
|
||||
.reserved0 = 0b00,
|
||||
.rinmute = 0b1,
|
||||
.rlinboth = 0b0,
|
||||
.reserved1 = 0,
|
||||
},
|
||||
.left_headphone_out = {
|
||||
.lhpvol = 0b1111001,
|
||||
.lzcen = 0b0,
|
||||
.lrhpboth = 0b0,
|
||||
.reserved0 = 0,
|
||||
},
|
||||
.right_headphone_out = {
|
||||
.rhpvol = 0b1111001,
|
||||
.rzcen = 0b0,
|
||||
.rlhpboth = 0b0,
|
||||
.reserved0 = 0,
|
||||
},
|
||||
.analog_audio_path_control = {
|
||||
.micboost = 0b0,
|
||||
.mutemic = 0b1,
|
||||
.insel = 0b0,
|
||||
.bypass = 0b1,
|
||||
.dacsel = 0b0,
|
||||
.sidetone = 0b0,
|
||||
.sideatt = 0b00,
|
||||
.reserved0 = 0,
|
||||
},
|
||||
.digital_audio_path_control = {
|
||||
.adchpd = 0b0,
|
||||
.deemp = 0b00,
|
||||
.dacmu = 0b1,
|
||||
.hpor = 0b0,
|
||||
.reserved0 = 0,
|
||||
},
|
||||
.power_down_control = {
|
||||
.lineinpd = 0b1,
|
||||
.micpd = 0b1,
|
||||
.adcpd = 0b1,
|
||||
.dacpd = 0b1,
|
||||
.outpd = 0b1,
|
||||
.oscpd = 0b0,
|
||||
.clkoutpd = 0b0,
|
||||
.poweroff = 0b1,
|
||||
.reserved0 = 0,
|
||||
},
|
||||
.digital_audio_interface_format = {
|
||||
.format = 0b10,
|
||||
.iwl = 0b10,
|
||||
.lrp = 0b0,
|
||||
.lrswap = 0b0,
|
||||
.ms = 0b0,
|
||||
.bclkinv = 0b0,
|
||||
.reserved0 = 0,
|
||||
},
|
||||
.sampling_control = {
|
||||
.usb_normal = 0b0,
|
||||
.bosr = 0b0,
|
||||
.sr = 0b0000,
|
||||
.clkidiv2 = 0b0,
|
||||
.clkodiv2 = 0b0,
|
||||
.reserved0 = 0,
|
||||
},
|
||||
.active_control = {
|
||||
.active = 0b0,
|
||||
.reserved0 = 0,
|
||||
},
|
||||
} };
|
||||
|
||||
class WM8731 {
|
||||
public:
|
||||
constexpr WM8731(
|
||||
I2C& bus,
|
||||
const I2C::address_t bus_address
|
||||
) : bus(bus),
|
||||
bus_address(bus_address)
|
||||
{
|
||||
}
|
||||
|
||||
void init() {
|
||||
reset();
|
||||
|
||||
write(PowerDownControl {
|
||||
.lineinpd = 1,
|
||||
.micpd = 0,
|
||||
.adcpd = 0,
|
||||
.dacpd = 0,
|
||||
.outpd = 0,
|
||||
.oscpd = 1,
|
||||
.clkoutpd = 1,
|
||||
.poweroff = 0,
|
||||
.reserved0 = 0,
|
||||
});
|
||||
|
||||
// write(SamplingControl {
|
||||
// .usb_normal = 0,
|
||||
// .bosr = 0,
|
||||
// .sr = 0,
|
||||
// .clkidiv2 = 0,
|
||||
// .clkodiv2 = 0,
|
||||
// .reserved0 = 0,
|
||||
// });
|
||||
|
||||
write(DigitalAudioInterfaceFormat {
|
||||
.format = 2,
|
||||
.iwl = 0,
|
||||
.lrp = 0,
|
||||
.lrswap = 0,
|
||||
.ms = 0,
|
||||
.bclkinv = 0,
|
||||
.reserved0 = 0,
|
||||
});
|
||||
|
||||
write(DigitalAudioPathControl {
|
||||
.adchpd = 0,
|
||||
.deemp = 0,
|
||||
.dacmu = 0,
|
||||
.hpor = 0,
|
||||
.reserved0 = 0,
|
||||
});
|
||||
|
||||
write(AnalogAudioPathControl {
|
||||
.micboost = 1, // Enable 20dB boost
|
||||
.mutemic = 0, // Disable mute (unmute)
|
||||
.insel = 1, // Microphone input to ADC
|
||||
.bypass = 0,
|
||||
.dacsel = 1,
|
||||
.sidetone = 0,
|
||||
.sideatt = 0,
|
||||
.reserved0 = 0,
|
||||
});
|
||||
|
||||
write(ActiveControl {
|
||||
.active = 1,
|
||||
.reserved0 = 0,
|
||||
});
|
||||
|
||||
set_line_in_volume(0.0_dB);
|
||||
headphone_mute();
|
||||
}
|
||||
|
||||
void reset() {
|
||||
write(0x0f, 0);
|
||||
}
|
||||
|
||||
void set_line_in_volume(const volume_t volume) {
|
||||
const auto normalized = line_in_gain_range.normalize(volume);
|
||||
auto n = normalized.centibel() / 15;
|
||||
|
||||
write(LeftLineIn {
|
||||
.linvol = static_cast<reg_t>(n),
|
||||
.reserved0 = 0,
|
||||
.linmute = 0,
|
||||
.lrinboth = 1,
|
||||
.reserved1 = 0,
|
||||
});
|
||||
}
|
||||
|
||||
void set_headphone_volume(const volume_t volume) {
|
||||
const auto normalized = headphone_gain_range.normalize(volume);
|
||||
auto n = normalized.centibel() / 10;
|
||||
|
||||
write(LeftHeadphoneOut {
|
||||
.lhpvol = static_cast<reg_t>(n),
|
||||
.lzcen = 1,
|
||||
.lrhpboth = 1,
|
||||
.reserved0 = 0,
|
||||
});
|
||||
}
|
||||
|
||||
void headphone_mute() {
|
||||
set_headphone_volume(headphone_gain_range.min);
|
||||
}
|
||||
|
||||
// void microphone_mute(const bool mute) {
|
||||
// map.r.analog_audio_path_control.mutemic = (mute ? 0 : 1);
|
||||
// write(Register::AnalogAudioPathControl);
|
||||
// }
|
||||
|
||||
// void set_adc_source(const ADCSource adc_source) {
|
||||
// map.r.analog_audio_path_control.insel = toUType(adc_source);
|
||||
// write(Register::AnalogAudioPathControl);
|
||||
// }
|
||||
|
||||
private:
|
||||
I2C& bus;
|
||||
const I2C::address_t bus_address;
|
||||
RegisterMap map { default_after_reset };
|
||||
|
||||
void write(const Register reg) {
|
||||
write(toUType(reg), map.w[toUType(reg)]);
|
||||
}
|
||||
|
||||
void write(const address_t reg_address, const reg_t value);
|
||||
|
||||
void write(const LeftLineIn value) {
|
||||
map.r.left_line_in = value;
|
||||
write(Register::LeftLineIn);
|
||||
}
|
||||
|
||||
void write(const RightLineIn value) {
|
||||
map.r.right_line_in = value;
|
||||
write(Register::RightLineIn);
|
||||
}
|
||||
|
||||
void write(const LeftHeadphoneOut value) {
|
||||
map.r.left_headphone_out = value;
|
||||
write(Register::LeftHeadphoneOut);
|
||||
}
|
||||
|
||||
void write(const RightHeadphoneOut value) {
|
||||
map.r.right_headphone_out = value;
|
||||
write(Register::RightHeadphoneOut);
|
||||
}
|
||||
|
||||
void write(const AnalogAudioPathControl value) {
|
||||
map.r.analog_audio_path_control = value;
|
||||
write(Register::AnalogAudioPathControl);
|
||||
}
|
||||
|
||||
void write(const DigitalAudioPathControl value) {
|
||||
map.r.digital_audio_path_control = value;
|
||||
write(Register::DigitalAudioPathControl);
|
||||
}
|
||||
|
||||
void write(const PowerDownControl value) {
|
||||
map.r.power_down_control = value;
|
||||
write(Register::PowerDownControl);
|
||||
}
|
||||
|
||||
void write(const DigitalAudioInterfaceFormat value) {
|
||||
map.r.digital_audio_interface_format = value;
|
||||
write(Register::DigitalAudioInterfaceFormat);
|
||||
}
|
||||
|
||||
void write(const SamplingControl value) {
|
||||
map.r.sampling_control = value;
|
||||
write(Register::SamplingControl);
|
||||
}
|
||||
|
||||
void write(const ActiveControl value) {
|
||||
map.r.active_control = value;
|
||||
write(Register::ActiveControl);
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace wm8731 */
|
||||
} /* namespace wolfson */
|
||||
|
||||
#endif/*__WM8731_H__*/
|
||||
Reference in New Issue
Block a user