mirror of
https://github.com/akuker/RASCSI.git
synced 2024-11-21 10:33:16 +00:00
Optimize setting the data gpio bits (#1022)
Co-authored-by: Tony Kuker <akuker@gmail.com>
This commit is contained in:
parent
52c2aa474f
commit
09ba19a24f
@ -77,6 +77,8 @@ bool GPIOBUS_BananaM2p::Init(mode_e mode)
|
||||
|
||||
InitializeGpio();
|
||||
|
||||
MakeTable();
|
||||
|
||||
// SetupSelEvent needs to be called AFTER Initialize GPIO. This function
|
||||
// reconfigures the SEL signal.
|
||||
if (!SetupSelEvent()) {
|
||||
@ -533,8 +535,8 @@ void GPIOBUS_BananaM2p::SetREQ(bool ast)
|
||||
uint8_t GPIOBUS_BananaM2p::GetDAT()
|
||||
{
|
||||
GPIO_FUNCTION_TRACE
|
||||
(void)Acquire();
|
||||
// TODO: This is inefficient, but it works...
|
||||
|
||||
Acquire();
|
||||
uint32_t data =
|
||||
((GetSignal(BPI_PIN_DT0) ? 0x01 : 0x00) << 0) | ((GetSignal(BPI_PIN_DT1) ? 0x01 : 0x00) << 1) |
|
||||
((GetSignal(BPI_PIN_DT2) ? 0x01 : 0x00) << 2) | ((GetSignal(BPI_PIN_DT3) ? 0x01 : 0x00) << 3) |
|
||||
@ -549,27 +551,27 @@ void GPIOBUS_BananaM2p::SetDAT(uint8_t dat)
|
||||
{
|
||||
GPIO_FUNCTION_TRACE
|
||||
|
||||
SetMode(BPI_PIN_DT0, OUT);
|
||||
SetMode(BPI_PIN_DT1, OUT);
|
||||
SetMode(BPI_PIN_DT2, OUT);
|
||||
SetMode(BPI_PIN_DT3, OUT);
|
||||
SetMode(BPI_PIN_DT4, OUT);
|
||||
SetMode(BPI_PIN_DT5, OUT);
|
||||
SetMode(BPI_PIN_DT6, OUT);
|
||||
SetMode(BPI_PIN_DT7, OUT);
|
||||
SetMode(BPI_PIN_DP, OUT);
|
||||
array<uint32_t, 12> gpio_reg_values = {0};
|
||||
|
||||
// TODO: This is inefficient, but it works...
|
||||
PinSetSignal(BPI_PIN_DT0, (dat & (1 << 0)) == 0); // NOSONAR: GCC 10 doesn't support shift operations on std::byte
|
||||
PinSetSignal(BPI_PIN_DT1, (dat & (1 << 1)) == 0); // NOSONAR: GCC 10 doesn't support shift operations on std::byte
|
||||
PinSetSignal(BPI_PIN_DT2, (dat & (1 << 2)) == 0); // NOSONAR: GCC 10 doesn't support shift operations on std::byte
|
||||
PinSetSignal(BPI_PIN_DT3, (dat & (1 << 3)) == 0); // NOSONAR: GCC 10 doesn't support shift operations on std::byte
|
||||
PinSetSignal(BPI_PIN_DT4, (dat & (1 << 4)) == 0); // NOSONAR: GCC 10 doesn't support shift operations on std::byte
|
||||
PinSetSignal(BPI_PIN_DT5, (dat & (1 << 5)) == 0); // NOSONAR: GCC 10 doesn't support shift operations on std::byte
|
||||
PinSetSignal(BPI_PIN_DT6, (dat & (1 << 6)) == 0); // NOSONAR: GCC 10 doesn't support shift operations on std::byte
|
||||
PinSetSignal(BPI_PIN_DT7, (dat & (1 << 7)) == 0); // NOSONAR: GCC 10 doesn't support shift operations on std::byte
|
||||
for (size_t gpio_num = 0; gpio_num < pintbl.size(); gpio_num++) {
|
||||
bool value;
|
||||
if (gpio_num < 8) {
|
||||
// data bits
|
||||
value = !(dat & (1 << gpio_num)); // NOSONAR: GCC 10 doesn't support shift operations on std::byte
|
||||
} else {
|
||||
// parity bit
|
||||
value = (__builtin_parity(dat) == 1);
|
||||
}
|
||||
|
||||
PinSetSignal(BPI_PIN_DP, __builtin_parity(dat) == 1);
|
||||
if (value) {
|
||||
uint32_t this_gpio = pintbl[gpio_num];
|
||||
int bank = SunXI::GPIO_BANK(this_gpio);
|
||||
int offset = SunXI::GPIO_NUM(this_gpio);
|
||||
gpio_reg_values[bank] |= (1 << offset);
|
||||
}
|
||||
}
|
||||
|
||||
sunxi_set_all_gpios(gpio_data_masks, gpio_reg_values);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
@ -589,89 +591,12 @@ const array<int, 19> GPIOBUS_BananaM2p::SignalTable = {BPI_PIN_DT0, BPI_PIN_DT1,
|
||||
//---------------------------------------------------------------------------
|
||||
void GPIOBUS_BananaM2p::MakeTable(void)
|
||||
{
|
||||
const array<int, 9> pintbl = {BPI_PIN_DT0, BPI_PIN_DT1, BPI_PIN_DT2, BPI_PIN_DT3, BPI_PIN_DT4,
|
||||
BPI_PIN_DT5, BPI_PIN_DT6, BPI_PIN_DT7, BPI_PIN_DP};
|
||||
for (auto this_gpio : pintbl) {
|
||||
int bank = SunXI::GPIO_BANK(this_gpio);
|
||||
int offset = (SunXI::GPIO_NUM(this_gpio));
|
||||
|
||||
array<bool, 256> tblParity;
|
||||
|
||||
// Create parity table
|
||||
for (uint32_t i = 0; i < 0x100; i++) {
|
||||
uint32_t bits = i;
|
||||
uint32_t parity = 0;
|
||||
for (int j = 0; j < 8; j++) {
|
||||
parity ^= bits & 1;
|
||||
bits >>= 1;
|
||||
}
|
||||
parity = ~parity;
|
||||
tblParity[i] = parity & 1;
|
||||
gpio_data_masks[bank] |= (1 << offset);
|
||||
}
|
||||
|
||||
#if SIGNAL_CONTROL_MODE == 0
|
||||
// Mask and setting data generation
|
||||
for (auto &tbl : tblDatMsk) {
|
||||
tbl.fill(-1);
|
||||
}
|
||||
for (auto &tbl : tblDatSet) {
|
||||
tbl.fill(0);
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < 0x100; i++) {
|
||||
// Bit string for inspection
|
||||
uint32_t bits = i;
|
||||
|
||||
// Get parity
|
||||
if (tblParity[i]) {
|
||||
bits |= (1 << 8);
|
||||
}
|
||||
|
||||
// Bit check
|
||||
for (int j = 0; j < 9; j++) {
|
||||
// Index and shift amount calculation
|
||||
int index = pintbl[j] / 10;
|
||||
int shift = (pintbl[j] % 10) * 3;
|
||||
|
||||
// Mask data
|
||||
tblDatMsk[index][i] &= ~(0x7 << shift);
|
||||
|
||||
// Setting data
|
||||
if (bits & 1) {
|
||||
tblDatSet[index][i] |= (1 << shift);
|
||||
}
|
||||
|
||||
bits >>= 1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (uint32_t i = 0; i < 0x100; i++) {
|
||||
// Bit string for inspection
|
||||
uint32_t bits = i;
|
||||
|
||||
// Get parity
|
||||
if (tblParity[i]) {
|
||||
bits |= (1 << 8);
|
||||
}
|
||||
|
||||
#if SIGNAL_CONTROL_MODE == 1
|
||||
// Negative logic is inverted
|
||||
bits = ~bits;
|
||||
#endif
|
||||
|
||||
// Create GPIO register information
|
||||
uint32_t gpclr = 0;
|
||||
uint32_t gpset = 0;
|
||||
for (int j = 0; j < 9; j++) {
|
||||
if (bits & 1) {
|
||||
gpset |= (1 << pintbl[j]);
|
||||
} else {
|
||||
gpclr |= (1 << pintbl[j]);
|
||||
}
|
||||
bits >>= 1;
|
||||
}
|
||||
|
||||
tblDatMsk[i] = gpclr;
|
||||
tblDatSet[i] = gpset;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool GPIOBUS_BananaM2p::GetDP() const
|
||||
@ -1058,6 +983,28 @@ void GPIOBUS_BananaM2p::sunxi_output_gpio(int pin, int value)
|
||||
pio->DAT |= (1 << num);
|
||||
}
|
||||
|
||||
void GPIOBUS_BananaM2p::sunxi_set_all_gpios(array<uint32_t, 12> &mask, array<uint32_t, 12> &value)
|
||||
{
|
||||
GPIO_FUNCTION_TRACE
|
||||
for (size_t bank = 0; bank < mask.size(); bank++) {
|
||||
if (mask[bank] == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
volatile SunXI::sunxi_gpio_t *pio;
|
||||
if (bank < 11) {
|
||||
pio = &(pio_map->gpio_bank[bank]);
|
||||
} else {
|
||||
pio = &(r_pio_map->gpio_bank[bank - 11]);
|
||||
}
|
||||
|
||||
uint32_t reg_val = pio->DAT;
|
||||
reg_val &= ~mask[bank];
|
||||
reg_val |= value[bank];
|
||||
pio->DAT = reg_val;
|
||||
}
|
||||
}
|
||||
|
||||
int GPIOBUS_BananaM2p::sunxi_input_gpio(int pin) const
|
||||
{
|
||||
GPIO_FUNCTION_TRACE
|
||||
|
@ -124,7 +124,7 @@ class GPIOBUS_BananaM2p : public GPIOBUS
|
||||
// Set SCSI I/O mode
|
||||
int GetMode(int pin) override;
|
||||
|
||||
bool GetSignal(int pin) const override;
|
||||
inline bool GetSignal(int pin) const override;
|
||||
|
||||
// Set SCSI output signal value
|
||||
void SetSignal(int pin, bool ast) override;
|
||||
@ -153,35 +153,12 @@ class GPIOBUS_BananaM2p : public GPIOBUS
|
||||
|
||||
bool SetupSelEvent();
|
||||
|
||||
#if !defined(__x86_64__) && !defined(__X86__)
|
||||
uint32_t baseaddr = 0; // Base address
|
||||
#endif
|
||||
|
||||
volatile uint32_t *gpio_map = nullptr;
|
||||
|
||||
// Timer control register
|
||||
volatile uint32_t *tmr_ctrl;
|
||||
|
||||
#if !defined(__x86_64__) && !defined(__X86__)
|
||||
volatile uint32_t *gicd = nullptr; // GIC Interrupt distributor register
|
||||
#endif
|
||||
|
||||
volatile uint32_t *gicc = nullptr; // GIC CPU interface register
|
||||
|
||||
array<uint32_t, 4> gpfsel; // GPFSEL0-4 backup values
|
||||
|
||||
array<uint32_t, 12> signals = {0}; // All bus signals
|
||||
|
||||
#if SIGNAL_CONTROL_MODE == 0
|
||||
array<array<uint32_t, 256>, 3> tblDatMsk; // Data mask table
|
||||
|
||||
array<array<uint32_t, 256>, 3> tblDatSet; // Data setting table
|
||||
#else
|
||||
array<uint32_t, 256> tblDatMsk = {}; // Data mask table
|
||||
|
||||
array<uint32_t, 256> tblDatSet = {}; // Table setting table
|
||||
#endif
|
||||
|
||||
int sunxi_setup(void);
|
||||
|
||||
void sunxi_set_pullupdn(int gpio, int pud);
|
||||
@ -206,13 +183,19 @@ class GPIOBUS_BananaM2p : public GPIOBUS
|
||||
|
||||
SBC_Version::sbc_version_type sbc_version;
|
||||
|
||||
SunXI::sunxi_gpio_reg_t saved_gpio_config;
|
||||
|
||||
static const array<int, 19> SignalTable;
|
||||
|
||||
void InitializeGpio();
|
||||
std::vector<int> gpio_banks;
|
||||
|
||||
// Note: These MUST be in order from bit 0 to bit 7 with parity as the last item in the array
|
||||
const array<int, 9> pintbl = {BPI_PIN_DT0, BPI_PIN_DT1, BPI_PIN_DT2, BPI_PIN_DT3, BPI_PIN_DT4,
|
||||
BPI_PIN_DT5, BPI_PIN_DT6, BPI_PIN_DT7, BPI_PIN_DP};
|
||||
|
||||
void sunxi_set_all_gpios(array<uint32_t, 12> &mask, array<uint32_t, 12> &value);
|
||||
|
||||
array<uint32_t, 12> gpio_data_masks = {0};
|
||||
|
||||
#if defined(__x86_64__) || defined(__X86__) || defined(__aarch64__)
|
||||
// The SEL_EVENT functions need to do something to prevent SonarCloud from
|
||||
// claiming they should be const
|
||||
|
Loading…
Reference in New Issue
Block a user