// Mikroelektronika mikroBUS (https://www.mikroe.com/mikrobus) // Remote I/O Server and Socket Services // Copyright (C)2020-2023, Philip Munts dba Munts Technologies. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. using IO.Objects.RemoteIO; using IO.Objects.RemoteIO.Platforms; namespace IO.Objects.RemoteIO.mikroBUS { /// /// Encapsulates mikroBUS shields on Remote I/O Protocol servers providing /// mikroBUS sockets). /// public static class Shield { /// /// Supported mikroBUS shields. /// public enum Kinds { /// /// Mikroelektronika BeagleBone Click Shield /// MIKROE-1596, /// with two mikroBUS sockets. (Obsolete, but still useful.) /// BeagleBoneClick2, /// /// Mikroelektronika mikroBUS Cape /// /// MIKROE-1857 with four mikroBUS sockets. /// BeagleBoneClick4, /// /// Raspberry Pi with Mikroelektronika Pi Click Shield /// /// MIKROE-1512/1513 for 26-pin expansion header, with one /// mikroBUS socket (Obsolete.) /// PiClick1, /// /// Raspberry Pi with Mikroelektronika Pi 2 Click Shield /// MIKROE-1879 /// for 40-pin expansion header, with two mikroBUS sockets. /// PiClick2, /// /// Mikroelektronika Pi 3 Click Shield /// MIKROE-2756 /// for 40-pin expansion header, with selectable on-board A/D /// converter and two mikroBUS sockets. /// PiClick3, /// /// PocketBeagle with /// female headers on top, with two mikroBUS sockets. /// /// /// Refer to /// http://git.munts.com/muntsos/doc/PocketBeaglePinout.pdf /// PocketBeagle, /// /// No known mikroBUS shield installed. /// Unknown = int.MaxValue } /// /// Returns the kind of mikroBUS shield that is installed on the Remote /// I/O Protocol server, as obtained from the SHIELDNAME /// environment variable. /// public static Kinds kind { get { if (System.Enum.TryParse(System.Environment.GetEnvironmentVariable("SHIELDNAME"), true, out Kinds shield)) return shield; else return Kinds.Unknown; } } /// /// Shared I2C bus that is common to all sockets on this /// shield. /// public static IO.Interfaces.I2C.Bus I2CBus = null; } /// /// Encapsulates mikroBUS sockets. /// public class Socket { private readonly struct SocketEntry { public readonly Shield.Kinds shield; public readonly int num; // mikroBUS GPIO pins public readonly int AN; public readonly int RST; public readonly int CS; public readonly int SCK; public readonly int MISO; public readonly int MOSI; public readonly int SDA; public readonly int SCL; public readonly int TX; public readonly int RX; public readonly int INT; public readonly int PWM; // mikroBUS devices public readonly int AIN; public readonly int I2CBus; public readonly int PWMOut; public readonly int SPIDev; public SocketEntry( Shield.Kinds shield, int num, // mikroBUS GPIO pins int AN, int RST, int CS, int SCK, int MISO, int MOSI, int SDA, int SCL, int TX, int RX, int INT, int PWM, // mikroBUS devices int AIN, int I2CBus, int PWMOut, int SPIDev) { this.shield = shield; this.num = num; // mikroBUS GPIO pins this.AN = AN; this.RST = RST; this.CS = CS; this.SCK = SCK; this.MISO = MISO; this.MOSI = MOSI; this.SDA = SDA; this.SCL = SCL; this.TX = TX; this.RX = RX; this.INT = INT; this.PWM = PWM; // mikroBUS devices this.AIN = AIN; this.I2CBus = I2CBus; this.PWMOut = PWMOut; this.SPIDev = SPIDev; } } private static readonly SocketEntry[] SocketTable = { new SocketEntry(Shield.Kinds.BeagleBoneClick2, 1, // mikroBUS GPIO pins AN: Device.Unavailable, RST: BeagleBone.GPIO45, CS: BeagleBone.GPIO44, SCK: BeagleBone.GPIO110, // Conflicts with SPI1 MISO: BeagleBone.GPIO111, // Conflicts with SPI1 MOSI: BeagleBone.GPIO112, // Conflicts with SPI1 SDA: BeagleBone.GPIO12, // Conflicts with I2C2 SCL: BeagleBone.GPIO13, // Conflicts with I2C2 TX: BeagleBone.GPIO15, // Conflicts with UART1 RX: BeagleBone.GPIO14, // Conflicts with UART1 INT: BeagleBone.GPIO27, PWM: BeagleBone.GPIO50, // Conflicts with EHRPWM1A // mikroBUS devices AIN: BeagleBone.AIN0, I2CBus: BeagleBone.I2C2, PWMOut: BeagleBone.EHRPWM1A, SPIDev: BeagleBone.SPI1_0), new SocketEntry(Shield.Kinds.BeagleBoneClick2, 2, // mikroBUS GPIO pins AN: Device.Unavailable, RST: BeagleBone.GPIO47, CS: BeagleBone.GPIO46, SCK: BeagleBone.GPIO110, // Conflicts with SPI1 MISO: BeagleBone.GPIO111, // Conflicts with SPI1 MOSI: BeagleBone.GPIO112, // Conflicts with SPI1 SDA: BeagleBone.GPIO12, // Conflicts with I2C2 SCL: BeagleBone.GPIO13, // Conflicts with I2C2 TX: BeagleBone.GPIO3, // Conflicts with UART2 RX: BeagleBone.GPIO2, // Conflicts with UART2 INT: BeagleBone.GPIO65, PWM: BeagleBone.GPIO22, // Conflicts with EHRPWM2A // mikroBUS devices AIN: BeagleBone.AIN1, I2CBus: BeagleBone.I2C2, PWMOut: BeagleBone.EHRPWM2A, SPIDev: BeagleBone.SPI1_1), new SocketEntry(Shield.Kinds.BeagleBoneClick4, 1, // mikroBUS GPIO pins AN: BeagleBone.GPIO61, // Conflicts with AIN3 RST: BeagleBone.GPIO60, CS: BeagleBone.GPIO113, // Conflicts with SPI1 SCK: BeagleBone.GPIO110, // Conflicts with SPI1 MISO: BeagleBone.GPIO111, // Conflicts with SPI1 MOSI: BeagleBone.GPIO112, // Conflicts with SPI1 SDA: BeagleBone.GPIO12, // Conflicts with I2C2 SCL: BeagleBone.GPIO13, // Conflicts with I2C2 TX: BeagleBone.GPIO3, // Conflicts with SPI0, UART2 RX: BeagleBone.GPIO2, // Conflicts with SPI0, UART2 INT: BeagleBone.GPIO48, PWM: BeagleBone.GPIO50, // Conflicts with EHRPWM1A // mikroBUS devices AIN: BeagleBone.AIN3, I2CBus: BeagleBone.I2C2, PWMOut: BeagleBone.EHRPWM1A, SPIDev: BeagleBone.SPI1_0), new SocketEntry(Shield.Kinds.BeagleBoneClick4, 2, // mikroBUS GPIO pins AN: BeagleBone.GPIO47, // Conflicts with AIN2 RST: BeagleBone.GPIO49, CS: BeagleBone.GPIO7, // Conflicts with SPI1 SCK: BeagleBone.GPIO110, // Conflicts with SPI1 MISO: BeagleBone.GPIO111, // Conflicts with SPI1 MOSI: BeagleBone.GPIO112, // Conflicts with SPI1 SDA: BeagleBone.GPIO12, // Conflicts with I2C2 SCL: BeagleBone.GPIO13, // Conflicts with I2C2 TX: BeagleBone.GPIO15, // Conflicts with UART1 RX: BeagleBone.GPIO14, // Conflicts with UART1 INT: BeagleBone.GPIO20, PWM: BeagleBone.GPIO51, // Conflicts with EHRPWM1B // mikroBUS devices AIN: BeagleBone.AIN2, I2CBus: BeagleBone.I2C2, PWMOut: BeagleBone.EHRPWM1B, SPIDev: BeagleBone.SPI1_1), new SocketEntry(Shield.Kinds.BeagleBoneClick4, 3, // mikroBUS GPIO pins AN: BeagleBone.GPIO44, // Conflicts with AIN1 RST: BeagleBone.GPIO26, CS: BeagleBone.GPIO5, // Conflicts with SPI0 SCK: BeagleBone.GPIO2, // Conflicts with SPI0, UART2 MISO: BeagleBone.GPIO3, // Conflicts with SPI0, UART2 MOSI: BeagleBone.GPIO4, // Conflicts with SPI0 SDA: BeagleBone.GPIO12, // Conflicts with I2C2 SCL: BeagleBone.GPIO13, // Conflicts with I2C2 TX: BeagleBone.GPIO15, // Conflicts with UART1 RX: BeagleBone.GPIO14, // Conflicts with UART1 INT: BeagleBone.GPIO65, PWM: BeagleBone.GPIO22, // Conflicts with EHRPWM2A // mikroBUS devices AIN: BeagleBone.AIN1, I2CBus: BeagleBone.I2C2, PWMOut: BeagleBone.EHRPWM2A, SPIDev: BeagleBone.SPI0_0), new SocketEntry(Shield.Kinds.BeagleBoneClick4, 4, // mikroBUS GPIO pins AN: BeagleBone.GPIO45, // Conflicts with AIN0 RST: BeagleBone.GPIO46, CS: BeagleBone.GPIO68, SCK: BeagleBone.GPIO110, // Conflicts with SPI1 MISO: BeagleBone.GPIO111, // Conflicts with SPI1 MOSI: BeagleBone.GPIO112, // Conflicts with SPI1 SDA: BeagleBone.GPIO12, // Conflicts with I2C2 SCL: BeagleBone.GPIO13, // Conflicts with I2C2 TX: BeagleBone.GPIO31, // Conflicts with UART4 RX: BeagleBone.GPIO30, // Conflicts with UART4 INT: BeagleBone.GPIO27, PWM: BeagleBone.GPIO23, // Conflicts with EHRPWM2B // mikroBUS devices AIN: BeagleBone.AIN0, I2CBus: BeagleBone.I2C2, PWMOut: BeagleBone.EHRPWM2B, SPIDev: Device.Unavailable), new SocketEntry(Shield.Kinds.PocketBeagle, 1, // Over the micro USB socket // mikroBUS GPIO pins AN: PocketBeagle.GPIO87, // Conflicts with AIN6 RST: PocketBeagle.GPIO89, CS: PocketBeagle.GPIO5, // Conflicts with SPI0 SCK: PocketBeagle.GPIO2, // Conflicts with SPI0 MISO: PocketBeagle.GPIO3, // Conflicts with SPI0 MOSI: PocketBeagle.GPIO4, // Conflicts with SPI0 SDA: PocketBeagle.GPIO14, // Conflicts with I2C1 SCL: PocketBeagle.GPIO15, // Conflicts with I2C1 TX: PocketBeagle.GPIO31, // Conflicts with UART4 RX: PocketBeagle.GPIO30, // Conflicts with UART4 INT: PocketBeagle.GPIO23, PWM: PocketBeagle.GPIO50, // Conflicts wtih PWM2:0 // mikroBUS devices AIN: PocketBeagle.AIN6, I2CBus: PocketBeagle.I2C1, PWMOut: PocketBeagle.PWM2_0, SPIDev: PocketBeagle.SPI0_0), new SocketEntry(Shield.Kinds.PocketBeagle, 2, // Over the micro SDHC socket // mikroBUS GPIO pins AN: PocketBeagle.GPIO86, // Conflicts with AIN5 RST: PocketBeagle.GPIO45, CS: PocketBeagle.GPIO19, // Conflicts with SPI1 SCK: PocketBeagle.GPIO7, // Conflicts with SPI1 MISO: PocketBeagle.GPIO40, // Conflicts with SPI1 MOSI: PocketBeagle.GPIO41, // Conflicts with SPI1 SDA: PocketBeagle.GPIO12, // Conflicts with I2C2 SCL: PocketBeagle.GPIO13, // Conflicts with I2C2 TX: PocketBeagle.GPIO43, // Conflicts with UART0 RX: PocketBeagle.GPIO42, // Conflicts with UART0 INT: PocketBeagle.GPIO26, PWM: PocketBeagle.GPIO110, // Conflicts with PWM0:0 // mikroBUS devices AIN: PocketBeagle.AIN5, I2CBus: PocketBeagle.I2C2, PWMOut: PocketBeagle.PWM0_0, SPIDev: PocketBeagle.SPI1_1), new SocketEntry(Shield.Kinds.PiClick1, 1, // mikroBUS GPIO pins AN: RaspberryPi.GPIO22, RST: RaspberryPi.GPIO4, CS: RaspberryPi.GPIO8, // Conflicts with SPI0 SCK: RaspberryPi.GPIO11, // Conflicts with SPI0 MISO: RaspberryPi.GPIO9, // Conflicts with SPI0 MOSI: RaspberryPi.GPIO10, // Conflicts with SPI0 SDA: RaspberryPi.GPIO2, // Conflicts with I2C1 SCL: RaspberryPi.GPIO3, // Conflicts with I2C1 TX: RaspberryPi.GPIO14, // Conflicts with UART0 RX: RaspberryPi.GPIO15, // Conflicts with UART0 INT: RaspberryPi.GPIO17, PWM: RaspberryPi.GPIO18, // Conflicts with PWM0 // mikroBUS devices AIN: Device.Unavailable, I2CBus: RaspberryPi.I2C1, PWMOut: RaspberryPi.PWM0, SPIDev: RaspberryPi.SPI0_0), new SocketEntry(Shield.Kinds.PiClick2, 1, // mikroBUS GPIO pins AN: RaspberryPi.GPIO4, RST: RaspberryPi.GPIO5, CS: RaspberryPi.GPIO8, // Conflicts with SPI0 SCK: RaspberryPi.GPIO11, // Conflicts with SPI0 MISO: RaspberryPi.GPIO9, // Conflicts with SPI0 MOSI: RaspberryPi.GPIO10, // Conflicts with SPI0 SDA: RaspberryPi.GPIO2, // Conflicts with I2C1 SCL: RaspberryPi.GPIO3, // Conflicts with I2C1 TX: RaspberryPi.GPIO14, // Conflicts with UART0 RX: RaspberryPi.GPIO15, // Conflicts with UART0 INT: RaspberryPi.GPIO6, PWM: RaspberryPi.GPIO18, // Conflicts with PWM0 // mikroBUS devices AIN: Device.Unavailable, I2CBus: RaspberryPi.I2C1, PWMOut: RaspberryPi.PWM0, SPIDev: RaspberryPi.SPI0_0), new SocketEntry(Shield.Kinds.PiClick2, 2, // mikroBUS GPIO pins AN: RaspberryPi.GPIO13, RST: RaspberryPi.GPIO19, CS: RaspberryPi.GPIO7, // Conflicts with SPI0 SCK: RaspberryPi.GPIO11, // Conflicts with SPI0 MISO: RaspberryPi.GPIO9, // Conflicts with SPI0 MOSI: RaspberryPi.GPIO10, // Conflicts with SPI0 SDA: RaspberryPi.GPIO2, // Conflicts with I2C1 SCL: RaspberryPi.GPIO3, // Conflicts with I2C1 TX: RaspberryPi.GPIO14, // Conflicts with UART0 RX: RaspberryPi.GPIO15, // Conflicts with UART0 INT: RaspberryPi.GPIO26, PWM: RaspberryPi.GPIO17, // mikroBUS devices AIN: Device.Unavailable, I2CBus: RaspberryPi.I2C1, PWMOut: Device.Unavailable, SPIDev: RaspberryPi.SPI0_1), new SocketEntry(Shield.Kinds.PiClick3, 1, // mikroBUS GPIO pins AN: RaspberryPi.GPIO4, // Switch AN1 must be in the RIGHT position RST: RaspberryPi.GPIO5, CS: RaspberryPi.GPIO8, // Conflicts with SPI0 SCK: RaspberryPi.GPIO11, // Conflicts with SPI0 MISO: RaspberryPi.GPIO9, // Conflicts with SPI0 MOSI: RaspberryPi.GPIO10, // Conflicts with SPI0 SDA: RaspberryPi.GPIO2, // Conflicts with I2C1 SCL: RaspberryPi.GPIO3, // Conflicts with I2C1 TX: RaspberryPi.GPIO14, // Conflicts with UART0 RX: RaspberryPi.GPIO15, // Conflicts with UART0 INT: RaspberryPi.GPIO6, PWM: RaspberryPi.GPIO18, // Conflicts with PWM0 // mikroBUS devices AIN: RaspberryPi.AIN0, // Switch AN1 must be in the LEFT position I2CBus: RaspberryPi.I2C1, PWMOut: RaspberryPi.PWM0, SPIDev: RaspberryPi.SPI0_0), new SocketEntry(Shield.Kinds.PiClick3, 2, // mikroBUS GPIO pins AN: RaspberryPi.GPIO13, // Switch AN2 must be in the RIGHT position RST: RaspberryPi.GPIO12, CS: RaspberryPi.GPIO7, // Conflicts with SPI0 SCK: RaspberryPi.GPIO11, // Conflicts with SPI0 MISO: RaspberryPi.GPIO9, // Conflicts with SPI0 MOSI: RaspberryPi.GPIO10, // Conflicts with SPI0 SDA: RaspberryPi.GPIO2, // Conflicts with I2C1 SCL: RaspberryPi.GPIO3, // Conflicts with I2C1 TX: RaspberryPi.GPIO14, // Conflicts with UART0 RX: RaspberryPi.GPIO15, // Conflicts with UART0 INT: RaspberryPi.GPIO26, PWM: RaspberryPi.GPIO17, // mikroBUS devices AIN: RaspberryPi.AIN1, // Switch AN2 must be in the LEFT position I2CBus: RaspberryPi.I2C1, PWMOut: Device.Unavailable, SPIDev: RaspberryPi.SPI0_1), }; private readonly SocketEntry myInfo; /// /// Constructor for a single mikroBUS socket. /// /// Socket number. /// mikroBUS shield kind. Zero /// indicates automatic detection using the Shield.kind /// property. public Socket(int num, Shield.Kinds shield = Shield.Kinds.Unknown) { if (shield == Shield.Kinds.Unknown) shield = Shield.kind; // Search for matching shield and socket number for (int i = 0; i < SocketTable.Length; i++) if ((SocketTable[i].shield == shield) && (SocketTable[i].num == num)) { myInfo = SocketTable[i]; return; } throw new System.Exception("Unable to find matching shield and socket number."); } /// /// Returns the GPIO pin designator for AN. /// public int AN { get { return myInfo.AN; } } /// /// Returns the GPIO pin designator for RST. /// public int RST { get { return myInfo.RST; } } /// /// Returns the GPIO pin designator for CS. /// public int CS { get { return myInfo.CS; } } /// /// Returns the GPIO pin designator for SCK. /// public int SCK { get { return myInfo.SCK; } } /// /// Returns the GPIO pin designator for MISO. /// public int MISO { get { return myInfo.MISO; } } /// /// Returns the GPIO pin designator for MOSI. /// public int MOSI { get { return myInfo.MOSI; } } /// /// Returns the GPIO pin designator for SDA. /// public int SDA { get { return myInfo.SDA; } } /// /// Returns the GPIO pin designator for SCL. /// public int SCL { get { return myInfo.SCL; } } /// /// Returns the GPIO pin designator for TX. /// public int TX { get { return myInfo.TX; } } /// /// Returns the GPIO pin designator for RX. /// public int RX { get { return myInfo.RX; } } /// /// Returns the GPIO pin designator for INT. /// public int INT { get { return myInfo.INT; } } /// /// Returns the GPIO pin designator for PWM. /// public int PWM { get { return myInfo.PWM; } } /// /// Returns the ADC input designator for AN. /// public int AIN { get { return myInfo.AIN; } } /// /// Returns the PWM output designator for PWM. /// public int PWMOut { get { return myInfo.PWMOut; } } /// /// Returns the I2C bus designator for this socket. /// public int I2CBus { get { return myInfo.I2CBus; } } /// /// Returns the SPI device designator for this socket. /// public int SPIDev { get { return myInfo.SPIDev; } } } }