Jelajahi Sumber

iot.pcx857x. Initial Import.

woollybah 5 tahun lalu
induk
melakukan
8fc753a82d
2 mengubah file dengan 251 tambahan dan 0 penghapusan
  1. 29 0
      core.mod/common.bmx
  2. 222 0
      pcx857x.mod/pcx857x.bmx

+ 29 - 0
core.mod/common.bmx

@@ -332,6 +332,35 @@ Struct SPinValuePair
 	
 End Struct
 
+Struct SPinVector32
+	Field pins:UInt
+	Field values:UInt
+	
+	Method New(pins:UInt, values:UInt)
+		Self.pins = pins
+		Self.values = values
+	End Method
+	
+	Method New(pinValues:SPinValuePair[])
+		pins = 0
+		values = 0
+		
+		For Local i:Int = 0 Until pinValues.length
+			Local pin:Int = pinValues[i].pinNumber
+			If pin < 0 Or pin >= 4 * 8 Then
+				Throw New TArgumentOutOfRangeException("pinValues")
+			End If
+			
+			Local bit:UInt = 1 Shl pin
+			pins :| bit
+			
+			If pinValues[i].pinValue = EPinValue.High Then
+				values :| bit
+			End If
+		Next
+	End Method
+	
+End Struct
 
 Function DelayMicroseconds(microseconds:Int, allowThreadYield:Int)
 	

+ 222 - 0
pcx857x.mod/pcx857x.bmx

@@ -0,0 +1,222 @@
+SuperStrict
+
+Module iot.pcx857x
+
+Import iot.core
+
+Type TPcx857x Extends TGpioDriver
+
+	Field device:TI2cDevice
+	Field masterGpioController:TGpioController
+	Field interrupt:Int
+	
+	Field pinModes:Short
+	
+	Field pinValues:Short
+	
+	Method New(device:TI2cDevice, interrupt:Int = -1, gpioController:TGpioController = Null)
+		If Not device Then
+			Throw New TArgumentNullException("device")
+		End If
+		
+		Self.device = device
+		Self.interrupt = interrupt
+		
+		If interrupt <> -1 Then
+			If Not gpioController Then
+				masterGpioController = New TGpioController
+			End If
+			masterGpioController.OpenPin(interrupt, EpinMode.Input)
+		End If
+		
+		' These controllers do not have commands, setting the pins to high designates
+		' them as able to recieve input. As we don't want to set high on pins intended
+		' for output we'll set all of the pins to low for our initial state.
+		If PinCount() = 8 Then
+			WriteByte(0)
+		Else
+			InternalWriteUInt16(0)
+		End If
+		
+		pinModes = $FFFF
+	End Method
+	
+	Method ReadByte:Byte()
+		Return device.ReadByte()
+	End Method
+	
+	Method WriteByte(value:Byte)
+		device.WriteByte(value)
+	End Method
+	
+	Method InternalReadUInt16:Short()
+		Local buffer:Byte Ptr = StackAlloc(2)
+		device.Read(buffer, 2)
+		Return buffer[0] | buffer[1] Shl 8
+	End Method
+	
+	Method InternalWriteUInt16(value:Short)
+		Local buffer:Byte Ptr = StackAlloc(2)
+		buffer[0] = value
+		buffer[1] = value Shr 8
+		device.Write(buffer, 2)
+	End Method
+	
+	Method ClosePin(pinNumber:Int)
+		' no-op
+	End Method
+	
+	Method Dispose()
+		device.Dispose()
+	End Method
+	
+	Method OpenPin(pinNumber:Int)
+		' no-op
+	End Method
+	
+	Method Read:EPinValue(pinNumber:Int)
+		Local values:SPinValuePair[] = New SPinValuePair[1]
+		values[0] = New SPinValuePair(pinNumber, EPinValue.Low)
+		
+		Read(values)
+		Return values[0].PinValue
+	End Method
+	
+	Method Read(pinValues:SPinValuePair[])
+		Local vec:SPinVector32 = New SPinVector32(pinValues)
+		
+		If vec.pins Shr PinCount() > 0 Then
+			ThrowInvalidPin("pinValues")
+		End If
+		
+		If vec.pins & pinModes Then
+			' One of the specified pins was set to output (1)
+			Throw New TInvalidOperationException("Cannot read from output pins.")
+		End If
+		
+		
+		Local data:Short
+		If PinCount() = 8 Then
+			data = ReadByte()
+		Else
+			data = InternalReadUInt16()
+		End If
+		
+		For Local i:Int = 0 Until pinValues.Length
+			Local pin:Int = pinValues[i].pinNumber
+			pinValues[i] = New SPinValuePair(pin, (data Shr pin) & 1)
+		Next
+		
+	End Method
+
+	Method ThrowInvalidPin(name:String)
+		Throw New TArgumentOutOfRangeException("Pin numbers must be in the range of 0 to " + (PinCount() - 1))
+	End Method
+
+	Method ValidatePinNumber(pinNumber:Int)
+		If pinNumber < 0 Or pinNumber >= PinCount() Then
+			ThrowInvalidPin("pinNumber")
+		End If
+	End Method
+	
+	Method SetPinMode(pinNumber:Int, pinMode:EPinMode)
+		ValidatePinNumber(pinNumber)
+		
+		If pinMode = EPinMode.Input Then
+			pinModes = (pinModes & ~(1 Shl pinNumber))
+		Else If pinMode = EPinMode.Output Then
+			pinModes = (pinModes | (1 Shl pinNumber))
+		Else
+			Throw New TArgumentOutOfRangeException("Only Input and Output modes are supported.")
+		End If
+		
+		WritePins(pinValues)
+	End Method
+	
+	Method WritePins(value:Short)
+		' We need to set all input pins to high
+		pinValues = (value | ~pinModes)
+		
+		If PinCount() = 8 Then
+			WriteByte(Byte(pinValues))
+		Else
+			InternalWriteUInt16(pinValues)
+		End If
+	End Method
+	
+	Method GetPinMode:EPinMode(pinNumber:Int)
+		If (pinModes & (1 Shl pinNumber)) = 0 Then
+			Return EPinMode.Input
+		Else
+			Return EPinMode.Output
+		End If
+	End Method
+	
+	Method Write(pinNumber:Int, value:EPinValue)
+		Local values:SPinValuePair[] = New SPinValuePair[1]
+		values[0] = New SPinValuePair(pinNumber, value)
+		
+		Write(values)
+	End Method
+
+	Method Write(pinValues:SPinValuePair[])
+		Local vec:SPinVector32 = New SPinVector32(pinValues)
+		
+		If vec.pins Shr PinCount() > 0 Then
+			ThrowInvalidPin("pinValues")
+		End If
+		
+		If vec.pins & ~pinModes Then
+			' One of the specified pins was set to input (0)
+			Throw New TInvalidOperationException("Cannot write to input pins.")
+		End If
+		
+		Local cpins:Short = Self.pinValues
+		cpins :& ~vec.pins
+		cpins :| vec.values
+		WritePins(cpins)
+	End Method
+	
+	Method ConvertPinNumberToLogicalNumberingScheme:Int(pinNumber:Int)
+		Return pinNumber
+	End Method
+	
+	Method IsPinModeSupported:Int(pinNumber:Int, pinMode:EPinMode)
+		Return pinMode = EpinMode.Output Or pinMode = EpinMode.Input
+	End Method
+	
+	Method AddCallbackForPinValueChangedEvent(pinNumber:Int, eventTypes:EPinEventTypes, context:Object, callback(context:Object, sender:Object, pinValueChangedEventArgs:SPinValueChangedEventArgs))
+		Throw New TNotImplementedException
+	End Method
+	
+	Method RemoveCallbackForPinValueChangedEvent(pinNumber:Int, callback(context:Object, sender:Object, pinValueChangedEventArgs:SPinValueChangedEventArgs))
+		Throw New TNotImplementedException
+	End Method
+	
+End Type
+
+Rem
+bbdoc: Base class for 8 bit I/O expanders.
+End Rem
+Type TPcx8574 Extends TPcx857x
+
+	Method New(device:TI2cDevice, interrupt:Int = -1, gpioController:TGpioController = Null)
+		Super.New(device, interrupt, gpioController)
+	End Method
+
+	Method PinCount:Int()
+		Return 8
+	End Method
+
+End Type
+
+Rem
+bbdoc: Remote 8-bit I/O expander for I2C-bus with interrupt.
+End Rem
+Type TPcf8574 Extends TPcx8574
+
+	Method New(device:TI2cDevice, interrupt:Int = -1, gpioController:TGpioController = Null)
+		Super.New(device, interrupt, gpioController)
+	End Method
+
+End Type