1
0
mirror of https://github.com/livingcomputermuseum/UniBone.git synced 2026-02-09 01:31:28 +00:00
Files
livingcomputermuseum.UniBone/10.01_base/2_src/arm/gpios.hpp

249 lines
7.5 KiB
C++

/* gpios.hpp: UniBone functions for Non-PRU GPIOs
Copyright (c) 2018, Joerg Hoppe
j_hoppe@t-online.de, www.retrocmp.com
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
JOERG HOPPE BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12-nov-2018 JH entered beta phase
*/
#ifndef _GPIOS_H_
#define _GPIOS_H_
#include <stdint.h>
#include <vector>
#include <string>
#include "logsource.hpp"
// device for a set of 32 gpio pins
typedef struct {
unsigned gpios_in_use; // so much pins from this bank are in use
uint32_t registerrange_addr_unmapped; //unmapped start addr of GPIo register range
unsigned registerrange_size;
// start addr of register bank, mapped into memory
volatile uint8_t *registerrange_start_addr;
// address of Output Enable Register, mapped into memory.
// bit<i> = 1: pin i is output, 0 = input
volatile uint32_t *oe_addr;
// Address of DATAIN register. Reflects the GPIO pin voltage levels.
volatile uint32_t *datain_addr;
// Address of DATAOUT register. Reflects the GPIO output pin voltage levels.
volatile uint32_t *dataout_addr;
uint32_t cur_dataout_val; // cached value of dataout register
// access to this is much faster than the GPIO dataut itself.
// mapped address of "set pin" register
// bit<i> := 1: gpio pin i is set to H level
volatile uint32_t *setdataout_addr;
// mapped address of "clear pin" register
// bit<i> := 1: gpio pin i is set to H level
volatile uint32_t *clrdataout_addr;
} gpio_bank_t;
/* access addresses for on gpio pin */
typedef struct {
char name[80];
unsigned tag; // marker for processing
int internal; // 1 = used internally, for P9.41, P).42 collision
int direction;
unsigned bank_idx; // GPIO=0,1,2,3
gpio_bank_t *bank; // GPIO=0,1,2,3
unsigned pin_in_bank; // 0..31
unsigned pin_in_bank_mask; // mask with bit 'gpio_pin_in_bank' set
unsigned linear_no; // linear index in /sys/class/gpio= 32*bank + pin_in_bnak
} gpio_config_t;
// direction of a pin
#define DIR_INPUT 0
#define DIR_OUTPUT 1
#define MAX_GPIOCOUNT 100
// test pins
// SET(1) -> pin auf H, LED OFF
#define ARM_DEBUG_PIN0(val) GPIO_SETVAL(gpios->led[0], !!(val))
#define ARM_DEBUG_PIN1(val) GPIO_SETVAL(gpios->led[1], !!(val))
#define ARM_DEBUG_PIN2(val) GPIO_SETVAL(gpios->led[2], !!(val))
#define ARM_DEBUG_PIN3(val) GPIO_SETVAL(gpios->led[3], !!(val))
#define ARM_DEBUG_PIN(n,val) GPIO_SETVAL(gpios->led[n], !!(val))
class gpios_c: public logsource_c {
private:
void bank_map_registers(unsigned bank_idx, unsigned unmapped_start_addr);
gpio_config_t *config(const char *name, int direction, unsigned bank_idx,
unsigned pin_in_bank);
void export_pin(gpio_config_t *pin);
public:
gpios_c();
// list of gpio register banks
gpio_bank_t banks[4];
// list of pins pins
gpio_config_t *pins[MAX_GPIOCOUNT + 1];
// mapped start addresses of register space for GPIOs
volatile void *registerrange_start_addr[4];
gpio_config_t *led[4], *swtch[4], *button, *reg_enable, *bus_enable, *i2c_panel_reset,
*reg_addr[3], *reg_write, *reg_datin[8], *reg_datout[8], *collision_p9_41,
*collision_p9_42;
void init(void);
void test_toggle(gpio_config_t *gpio);
void test_loopback(void);
};
#define BUSLATCHES_COUNT 8
// save current state uf gpios and registers,
// to suppress redundant write accesses
typedef struct {
// # of bits in each register connected bidirectionally to UNIBUS
// ( for example, LTC ignored)
unsigned bidi_bitwidth[BUSLATCHES_COUNT]; // # of bits in each
unsigned bidi_bitmask[BUSLATCHES_COUNT]; // mask with valid bits
bool read_inverted[BUSLATCHES_COUNT]; // true: read back inverted with respect to write levels
// current signal state, used for optimization
unsigned cur_output_enable; // state of ENABLE
unsigned cur_reg_sel; // state of SEL A0,A1,A2
unsigned cur_reg_val[BUSLATCHES_COUNT]; // content of output latches
} buslatches_t;
extern gpios_c *gpios; // singleton
extern buslatches_t buslatches;
// merges the bits of unshifted_val into the gpio output register
// of bank[idx]. target position is given by bitpos, bitfield size by bitmask
// This macro is optimized assuming that writing a memorymapped GPIO register
// takes much longer than ARM internal operations.
#define GPIO_OUTPUTBITS(bank,bitpos,bitmask,unshifted_val) do { \
unsigned tmp = (bank)->cur_dataout_val ; \
tmp &= ~((bitmask) << (bitpos)) ; /* erase bitfield*/ \
tmp |= ((unshifted_val) & (bitmask)) << (bitpos) ; /* copy val to bitfield*/ \
(bank)->cur_dataout_val = *((bank)->dataout_addr) = tmp ; \
} while(0)
// set a value by writing a bit mask into output register
#define GPIO_SETVAL(gpio,val) GPIO_OUTPUTBITS((gpio)->bank, (gpio)->pin_in_bank, 1, (val) )
// get a value by reading value register
// Getval(input) reads pin. Getval(output) reads values set.
#define GPIO_GETVAL(gpio) ( \
(gpio)->direction == DIR_OUTPUT ? \
(!! ( *((gpio)->bank->dataout_addr) & (gpio)->pin_in_bank_mask ) ) \
: (!! ( *((gpio)->bank->datain_addr) & (gpio)->pin_in_bank_mask ) ) \
)
// raw 1 bit signal traces
typedef struct {
unsigned reg_sel;
unsigned bit_nr;
unsigned is_input; // 0 = "74LVTH541 <- DS8641" ; 1 = "74LS377 -> DS8641"
unsigned is_inverted; // only BG*_OUT
const char *unibus_name; // UNIBUS signal name
const char *path; // long info with net list
} buslatches_wire_info_t;
extern buslatches_wire_info_t buslatches_wire_info[];
// compound unibus signals
class unibus_signal_info_c {
public:
enum id_enum {
ub_address, ub_data, ub_control, // c1,c0
ub_msyn,
ub_ssyn,
ub_pa,
ub_pb,
ub_intr,
ub_br4,
ub_br5,
ub_br6,
ub_br7,
ub_bg4,
ub_bg5,
ub_bg6,
ub_bg7,
ub_npr,
ub_npg,
ub_sack,
ub_bbsy,
ub_init,
ub_aclo,
ub_dclo
};
id_enum id;
std::string name;
unsigned bitwidth;
unibus_signal_info_c() {
}
;
unibus_signal_info_c(id_enum id, std::string name, unsigned bitwidth);
};
class unibus_signals_c {
public:
unibus_signals_c();
std::vector<unibus_signal_info_c> signals;
unsigned max_name_len();
unsigned size();
void set_val(enum unibus_signal_info_c::id_enum id, unsigned value);
unsigned get_val(enum unibus_signal_info_c::id_enum id);
};
extern unibus_signals_c *unibus_signals; // singleton
void buslatches_output_enable(bool enable);
void buslatches_register(void);
void buslatches_pru_reset(void);
buslatches_wire_info_t *buslatches_get_wire_info(const char * unibus_name, unsigned is_input);
void buslatches_setval(unsigned reg_sel, unsigned bitmask, unsigned val);
unsigned buslatches_getval(unsigned reg_sel);
void buslatches_test_simple_pattern(unsigned pattern, unsigned reg_sel);
void buslatches_test_simple_pattern_multi(unsigned pattern);
void buslatches_test_timing(uint8_t addr_0_7, uint8_t addr_8_15, uint8_t data_0_7,
uint8_t data_8_15);
#endif // _GPIOS_H_