diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Datasheet/AS1115-BSST.pdf b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Datasheet/AS1115-BSST.pdf
new file mode 100644
index 0000000000..702987db18
Binary files /dev/null and b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Datasheet/AS1115-BSST.pdf differ
diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/As1115.Enums.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/As1115.Enums.cs
new file mode 100644
index 0000000000..afe6568dd0
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/As1115.Enums.cs
@@ -0,0 +1,132 @@
+namespace Meadow.Foundation.ICs.IOExpanders
+{
+ public partial class As1115
+ {
+ ///
+ /// Valid addresses for the sensor.
+ ///
+ public enum Addresses : byte
+ {
+ ///
+ /// Bus address 0x00
+ ///
+ Address_0x00 = 0x00,
+ ///
+ /// Default bus address
+ ///
+ Default = Address_0x00
+ }
+
+ ///
+ /// The decode mode used for displaying pixels or characters
+ ///
+ public enum DecodeMode : byte
+ {
+ ///
+ /// Hexicemial charcter encoding for 7-segment displays
+ /// characters 0 to 9, E, H, L, P, and -
+ ///
+ //Hexidecimal,
+ ///
+ /// BCD character encoding for 7-segment displays
+ /// characters 0 to 9 and A to F
+ ///
+ //BCD,
+ ///
+ /// Direct pixel mapping for 8x8 matrix displays (default)
+ ///
+ Pixel,
+ }
+
+ ///
+ /// Key scan buttons
+ ///
+ public enum KeyScanButtonType : byte
+ {
+ ///
+ /// Button 1
+ /// Key A: 127, Key B: 255
+ ///
+ Button1,
+ ///
+ /// Button 2
+ /// Key A: 191, Key B: 255
+ ///
+ Button2,
+ ///
+ /// Button 3
+ /// Key A: 223, Key B: 255
+ ///
+ Button3,
+ ///
+ /// Button 4
+ /// Key A: 239, Key B: 255
+ ///
+ Button4,
+ ///
+ /// Button 5
+ /// Key A: 247, Key B: 255
+ ///
+ Button5,
+ ///
+ /// Button 6
+ /// Key A: 251, Key B: 255
+ ///
+ Button6,
+ ///
+ /// Button 7
+ /// Key A: 253, Key B: 255
+ ///
+ Button7,
+ ///
+ /// Button 8
+ /// Key A: 254, Key B: 255
+ ///
+ Button8,
+ ///
+ /// Button 9
+ /// Key A: 255, Key B: 127
+ ///
+ Button9,
+ ///
+ /// Button 10
+ /// Key A: 255, Key B: 191
+ ///
+ Button10,
+ ///
+ /// Button 11
+ /// Key A: 255, Key B: 223
+ ///
+ Button11,
+ ///
+ /// Button 11
+ /// Key A: 255, Key B: 239
+ ///
+ Button12,
+ ///
+ /// Button 12
+ /// Key A: 255, Key B: 247
+ ///
+ Button13,
+ ///
+ /// Button 13
+ /// Key A: 255, Key B: 251
+ ///
+ Button14,
+ ///
+ /// Button 15
+ /// Key A: 255, Key B: 253
+ ///
+ Button15,
+ ///
+ /// Button 16
+ /// Key A: 255, Key B: 254
+ ///
+ Button16,
+ ///
+ /// No button pressed or selected
+ ///
+ None,
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/As1115.Registers.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/As1115.Registers.cs
new file mode 100644
index 0000000000..889734b9a1
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/As1115.Registers.cs
@@ -0,0 +1,63 @@
+namespace Meadow.Foundation.ICs.IOExpanders
+{
+ public partial class As1115
+ {
+ const byte REG_DIGIT0 = 0x01;
+ const byte REG_DIGIT1 = 0x02;
+ const byte REG_DIGIT2 = 0x03;
+ const byte REG_DIGIT3 = 0x04;
+ const byte REG_DIGIT4 = 0x05;
+ const byte REG_DIGIT5 = 0x06;
+ const byte REG_DIGIT6 = 0x07;
+ const byte REG_DIGIT7 = 0x08;
+
+ const byte REG_DECODE_MODE = 0x09;
+ const byte REG_GLOBAL_INTEN = 0x0A;
+ const byte REG_SCAN_LIMIT = 0x0B;
+ const byte REG_SHUTDOWN = 0x0C;
+ const byte REG_SELF_ADDR = 0x2D;
+ const byte REG_FEATURE = 0x0E;
+ const byte REG_DISP_TEST = 0x0F;
+
+ const byte REG_DIGIT01_INTEN = 0x10;
+ const byte REG_DIGIT23_INTEN = 0x11;
+ const byte REG_DIGIT45_INTEN = 0x12;
+ const byte REG_DIGIT67_INTEN = 0x13;
+
+ const byte REG_DIGIT0_DIAG = 0x14;
+ const byte REG_DIGIT1_DIAG = 0x15;
+ const byte REG_DIGIT2_DIAG = 0x16;
+ const byte REG_DIGIT3_DIAG = 0x17;
+ const byte REG_DIGIT4_DIAG = 0x18;
+ const byte REG_DIGIT5_DIAG = 0x19;
+ const byte REG_DIGIT6_DIAG = 0x1A;
+ const byte REG_DIGIT7_DIAG = 0x1B;
+
+ const byte REG_KEYA = 0x1C;
+ const byte REG_KEYB = 0x1D;
+
+ const byte DECODE_RAW = 0x00;
+ const byte DECODE_FONT = 0x01;
+ const byte DECODE_ALL_RAW = 0x00;
+ const byte DECODE_ALL_FONT = 0xFF;
+
+ const byte FONT_CODEB = 0x00;
+ const byte FONT_HEX = 0x01;
+
+ const byte REG_FEATURE_EXTCLK = 0x00;
+ const byte REG_FEATURE_RESET = 0x01;
+ const byte REG_FEATURE_FONT = 0x02;
+ const byte REG_FEATURE_BLINK = 0x04;
+ const byte REG_FEATURE_BLINKFREQ = 0x05;
+ const byte REG_FEATURE_BLINKSYNC = 0x06;
+ const byte REG_FEATURE_BLINKSTART = 0x07;
+
+ const byte REG_SHUTDOWN_SHUTDOWN = 0x00;
+ const byte REG_SHUTDOWN_RUNNING = 0x01;
+ const byte REG_SHUTDOWN_RESET_FEATUREREG = 0x00;
+ const byte REG_SHUTDOWN_PRESERVE_FEATUREREG = 0x80;
+
+ const byte DP_OFF = 0x00;
+ const byte DP_ON = 0x01;
+ }
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/As1115.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/As1115.cs
new file mode 100644
index 0000000000..6dc0f7e341
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/As1115.cs
@@ -0,0 +1,391 @@
+using Meadow.Foundation.Graphics;
+using Meadow.Foundation.Graphics.Buffers;
+using Meadow.Hardware;
+using Meadow.Peripherals.Sensors.Buttons;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+
+namespace Meadow.Foundation.ICs.IOExpanders
+{
+ public partial class As1115 : IGraphicsDisplay, IDisposable
+ {
+ ///
+ /// Event raised when any key scan button is pressed
+ ///
+ public event EventHandler KeyScanPressStarted = null;
+
+ ///
+ /// Event raised when any key scan button is released
+ ///
+ public event EventHandler KeyScanPressEnded = null;
+
+ ///
+ /// Readonly collection that contains all 16 key scan button objects
+ ///
+ public ReadOnlyDictionary KeyScanButtons { get; protected set; }
+
+ ///
+ /// Helper method to get IButton object references for keyscan buttons
+ ///
+ /// The button type
+ /// The button object reference
+ public IButton GetButton(KeyScanButtonType buttonType) => KeyScanButtons[buttonType];
+
+ ///
+ /// Last button pressed, used internally to raise key up events
+ ///
+ KeyScanButtonType lastButtonPressed = KeyScanButtonType.None;
+
+ ///
+ /// As1115 I2C driver
+ ///
+ protected II2cPeripheral i2cPeripheral;
+
+ ///
+ /// The display color mode (1 bit per pixel)
+ ///
+ public ColorType ColorMode => ColorType.Format1bpp;
+
+ ///
+ /// Display width in pixels for 8x8 matrix displays
+ ///
+ public int Width => 8;
+
+ ///
+ /// Display height in pixels for 8x8 matrix displays
+ ///
+ public int Height => 8;
+
+ ///
+ /// The buffer that holds the pixel data for 8x8 matrix displays
+ ///
+ public IPixelBuffer PixelBuffer => buffer;
+
+ ///
+ /// The buffer used to store pixel data
+ ///
+ readonly Buffer1bpp buffer = new Buffer1bpp(8, 8);
+
+ ///
+ /// Is the peripheral disposed
+ ///
+ public bool IsDisposed { get; private set; }
+
+ readonly IDigitalInputPort interruptPort;
+
+ ///
+ /// Create a new AS1115 object using the default parameters for
+ ///
+ /// Meadow device object
+ /// I2cBus connected to display
+ /// Interrupt pin
+ /// Address of the bus on the I2C display.
+ public As1115(IMeadowDevice device, II2cBus i2cBus, IPin buttonInterruptPin,
+ byte address = (byte)Addresses.Default)
+ {
+ i2cPeripheral = new I2cPeripheral(i2cBus, address);
+
+ interruptPort = device.CreateDigitalInputPort(buttonInterruptPin,
+ InterruptMode.EdgeFalling,
+ ResistorMode.InternalPullUp);
+
+ interruptPort.Changed += InterruptPort_Changed;
+
+ Initialize();
+ }
+
+ void Initialize()
+ {
+ var keyDictionary = new Dictionary();
+
+ //instantiate IButton objects
+ for (int i = 0; i < 16; i++)
+ {
+ keyDictionary.Add((KeyScanButtonType)i, new KeyScanButton());
+ }
+
+ KeyScanButtons = new ReadOnlyDictionary(keyDictionary);
+
+ i2cPeripheral.WriteRegister(REG_SHUTDOWN, REG_SHUTDOWN_RUNNING | REG_SHUTDOWN_RESET_FEATUREREG);
+
+ i2cPeripheral.WriteRegister(REG_SCAN_LIMIT, 0x07);
+
+ SetDecodeMode(DecodeMode.Pixel);
+
+ byte[] data = new byte[2];
+
+ //read the key scan registers to clear
+ i2cPeripheral.ReadRegister(REG_KEYA, data);
+ }
+
+ private void InterruptPort_Changed(object sender, DigitalPortResult e)
+ {
+ byte[] data = new byte[2];
+ i2cPeripheral.ReadRegister(REG_KEYA, data);
+
+ var keyScanButton = GetButtonFromKeyScanRegister(data[0], data[1]);
+
+ if (keyScanButton != KeyScanButtonType.None)
+ {
+ KeyScanPressStarted?.Invoke(this, new KeyScanEventArgs(keyScanButton, data[0], data[1]));
+
+ KeyScanButtons[keyScanButton].Update(true);
+
+ lastButtonPressed = keyScanButton;
+ }
+ else
+ {
+ KeyScanPressEnded?.Invoke(this, new KeyScanEventArgs(lastButtonPressed, data[0], data[1]));
+
+ if(lastButtonPressed != KeyScanButtonType.None)
+ {
+ KeyScanButtons[lastButtonPressed].Update(false);
+ }
+ }
+ }
+
+ KeyScanButtonType GetButtonFromKeyScanRegister(byte keyA, byte keyB)
+ {
+ KeyScanButtonType ret;
+
+ if (keyA == 255)
+ {
+ ret = keyB switch
+ {
+ 127 => KeyScanButtonType.Button9,
+ 191 => KeyScanButtonType.Button10,
+ 223 => KeyScanButtonType.Button11,
+ 239 => KeyScanButtonType.Button12,
+ 247 => KeyScanButtonType.Button13,
+ 251 => KeyScanButtonType.Button14,
+ 253 => KeyScanButtonType.Button15,
+ 254 => KeyScanButtonType.Button16,
+ _ => KeyScanButtonType.None,
+ };
+ }
+ else if(keyB == 255)
+ {
+ ret = keyA switch
+ {
+ 127 => KeyScanButtonType.Button1,
+ 191 => KeyScanButtonType.Button2,
+ 223 => KeyScanButtonType.Button3,
+ 239 => KeyScanButtonType.Button4,
+ 247 => KeyScanButtonType.Button5,
+ 251 => KeyScanButtonType.Button6,
+ 253 => KeyScanButtonType.Button7,
+ 254 => KeyScanButtonType.Button8,
+ _ => KeyScanButtonType.None,
+ };
+ }
+ else
+ {
+ ret = KeyScanButtonType.None;
+ }
+ return ret;
+ }
+
+ ///
+ /// Enable or disable display blinking
+ ///
+ /// Display will blink if true
+ /// True for fast blink (period of 1s), False for slow blink (period of 2s)
+ public void EnableBlink(bool isEnabled, bool fastBlink = true)
+ {
+ var reg = i2cPeripheral.ReadRegister(REG_FEATURE);
+
+ byte mask = 1 << REG_FEATURE_BLINK;
+
+ if(isEnabled)
+ {
+ reg |= mask;
+ }
+ else
+ {
+ reg &= (byte)~mask;
+ }
+
+ mask = 1 << REG_FEATURE_BLINKFREQ;
+ if (!fastBlink)
+ {
+ reg |= mask;
+ }
+ else
+ {
+ reg &= (byte)~mask;
+ }
+
+ i2cPeripheral.WriteRegister(REG_FEATURE, reg);
+ }
+
+ ///
+ /// Set the display decode mode
+ /// Hexidecimal for matrix leds, or character for 7-segment displays
+ ///
+ /// The decode mode enum
+ /// Not currently supported - driver is pixel mode only
+ void SetDecodeMode(DecodeMode mode)
+ {
+ buffer.Clear(true);
+
+ switch (mode)
+ {
+ case DecodeMode.Pixel:
+ i2cPeripheral.WriteRegister(REG_DECODE_MODE, 0);
+ break;
+ }
+ }
+
+ ///
+ /// Set display intensity (0-15)
+ ///
+ /// Instensity from 0-15 (clamps above 15)
+ public void SetIntensity(byte intensity)
+ {
+ intensity = Math.Max(intensity, (byte)15);
+
+ i2cPeripheral.WriteRegister(REG_GLOBAL_INTEN, intensity);
+ }
+
+ ///
+ /// Enable/disable test mode
+ ///
+ /// True to enable, false to disable
+ public void TestMode(bool testOn)
+ {
+ i2cPeripheral.WriteRegister(REG_DECODE_MODE, (byte)(testOn?0x01:0x00));
+ }
+
+ ///
+ /// Update the display
+ ///
+ public void Show()
+ {
+ i2cPeripheral.WriteRegister(REG_DIGIT0, buffer.Buffer[0]);
+ i2cPeripheral.WriteRegister(REG_DIGIT1, buffer.Buffer[1]);
+ i2cPeripheral.WriteRegister(REG_DIGIT2, buffer.Buffer[2]);
+ i2cPeripheral.WriteRegister(REG_DIGIT3, buffer.Buffer[3]);
+ i2cPeripheral.WriteRegister(REG_DIGIT4, buffer.Buffer[4]);
+ i2cPeripheral.WriteRegister(REG_DIGIT5, buffer.Buffer[5]);
+ i2cPeripheral.WriteRegister(REG_DIGIT6, buffer.Buffer[6]);
+ i2cPeripheral.WriteRegister(REG_DIGIT7, buffer.Buffer[7]);
+ }
+
+ ///
+ /// Update the display from the display buffer
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void Show(int left, int top, int right, int bottom)
+ {
+ Show();
+ }
+
+ ///
+ /// Clear the display buffer
+ ///
+ /// If true, update the display
+ public void Clear(bool updateDisplay = false)
+ {
+ buffer.Clear();
+ if(updateDisplay) { Show(); }
+ }
+
+ ///
+ /// Fill the display buffer with a color
+ /// Black will clear the display, any other color will turn on all leds
+ ///
+ /// The color to fill
+ /// Update the display
+ public void Fill(Color fillColor, bool updateDisplay = false)
+ {
+ buffer.Fill(fillColor);
+ if (updateDisplay) { Show(); }
+ }
+
+ ///
+ /// Fill a region of the display buffer with a color
+ /// Black will clear the display, any other color will turn on all leds
+ ///
+ /// X postion in pixels
+ /// Y position in pixels
+ /// Width in pixels
+ /// Height in pixels
+ /// Color to fill - Black will turn pixels off, any color will turn pixels on
+ public void Fill(int x, int y, int width, int height, Color fillColor)
+ {
+ buffer.Fill(x, y, width, height, fillColor);
+ }
+
+ ///
+ /// Draw a pixel at a given location
+ ///
+ /// X postion in pixels
+ /// Y position in pixels
+ /// Color to draw - Black will turn pixels off, any color will turn pixels on
+ public void DrawPixel(int x, int y, Color color)
+ {
+ buffer.SetPixel(x, y, color);
+ }
+
+ ///
+ /// Draw a pixel at a given location
+ ///
+ /// X postion in pixels
+ /// Y position in pixels
+ /// If true, turn led on at location
+ public void DrawPixel(int x, int y, bool colored)
+ {
+ buffer.SetPixel(x, y, colored);
+ }
+
+ ///
+ /// Invert pixel at location (switch on/off)
+ ///
+ /// X postion in pixels
+ /// Y position in pixels
+ public void InvertPixel(int x, int y)
+ {
+ buffer.InvertPixel(x, y);
+ }
+
+ ///
+ /// Write a pixel buffer to the display buffer
+ ///
+ /// X postion in pixels
+ /// Y position in pixels
+ /// Display buffer to write
+ public void WriteBuffer(int x, int y, IPixelBuffer displayBuffer)
+ {
+ buffer.WriteBuffer(x, y, displayBuffer);
+ }
+
+ ///
+ /// Dispose peripheral
+ ///
+ ///
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!IsDisposed)
+ {
+ if (disposing)
+ {
+ interruptPort.Dispose();
+ }
+ IsDisposed = true;
+ }
+ }
+
+ ///
+ /// Dispose Peripheral
+ ///
+ public void Dispose()
+ {
+ Dispose(disposing: true);
+ GC.SuppressFinalize(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/ICs.IOExpanders.As1115.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/ICs.IOExpanders.As1115.csproj
new file mode 100644
index 0000000000..b60c26fbed
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/ICs.IOExpanders.As1115.csproj
@@ -0,0 +1,23 @@
+
+
+ true
+ icon.png
+ Wilderness Labs, Inc
+ netstandard2.1
+ Library
+ As1115
+ Wilderness Labs, Inc
+ http://developer.wildernesslabs.co/Meadow/Meadow.Foundation/
+ Meadow.Foundation.ICs.IOExpanders.As1115
+ https://github.com/WildernessLabs/Meadow.Foundation
+ Meadow.Foundation, IOExpanders, As1115, led, driver, keyscan
+ 0.1.0
+ true
+ AS1115 I2C IO expander, led driver, character display controller and keyscan
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/KeyScanButton.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/KeyScanButton.cs
new file mode 100644
index 0000000000..28c3534f53
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/KeyScanButton.cs
@@ -0,0 +1,108 @@
+using Meadow.Peripherals.Sensors.Buttons;
+using System;
+
+namespace Meadow.Foundation.ICs.IOExpanders
+{
+ public class KeyScanButton : IButton
+ {
+ public TimeSpan LongClickedThreshold { get; set; }
+
+ public bool State { get; private set; }
+
+ ///
+ /// Raised when a press starts (the button is pushed down)
+ ///
+ public event EventHandler PressStarted;
+
+ ///
+ /// Raised when a press ends (the button is released)
+ ///
+ public event EventHandler PressEnded;
+
+ ///
+ /// Raised when the button circuit is re-opened after it has been closed (at the end of a press)
+ ///
+ public event EventHandler Clicked;
+
+ ///
+ /// Raised when the button circuit is pressed for LongPressDuration
+ ///
+ public event EventHandler LongClicked;
+
+ ///
+ /// Maximum DateTime value when the button was just pushed
+ ///
+ protected DateTime buttonPressStart = DateTime.MaxValue;
+
+ ///
+ /// Update the button state
+ /// true for pressed, false for released
+ ///
+ ///
+ public void Update(bool state)
+ {
+ if (state == true && State == false)
+ { // save our press start time (for long press event)
+ buttonPressStart = DateTime.Now;
+
+ RaisePressStarted();
+ }
+ else if (state == false && State == true)
+ { // calculate the press duration
+ TimeSpan pressDuration = DateTime.Now - buttonPressStart;
+
+ // reset press start time
+ buttonPressStart = DateTime.MaxValue;
+
+ // if it's a long press, raise our long press event
+ if (LongClickedThreshold > TimeSpan.Zero && pressDuration > LongClickedThreshold)
+ {
+ RaiseLongClicked();
+ }
+ else
+ {
+ RaiseClicked();
+ }
+
+ if (pressDuration.TotalMilliseconds > 0)
+ { // raise the other events
+ RaisePressEnded();
+ }
+ }
+
+ State = state;
+ }
+
+ ///
+ /// Raised when the button circuit is re-opened after it has been closed (at the end of a �press�).
+ ///
+ protected virtual void RaiseClicked()
+ {
+ Clicked?.Invoke(this, EventArgs.Empty);
+ }
+
+ ///
+ /// Raised when a press starts (the button is pushed down; circuit is closed).
+ ///
+ protected virtual void RaisePressStarted()
+ {
+ PressStarted?.Invoke(this, new EventArgs());
+ }
+
+ ///
+ /// Raised when a press ends (the button is released; circuit is opened).
+ ///
+ protected virtual void RaisePressEnded()
+ {
+ PressEnded?.Invoke(this, new EventArgs());
+ }
+
+ ///
+ /// Raised when the button circuit is pressed for at least 500ms.
+ ///
+ protected virtual void RaiseLongClicked()
+ {
+ LongClicked?.Invoke(this, new EventArgs());
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/KeyScanEventArgs.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/KeyScanEventArgs.cs
new file mode 100644
index 0000000000..e487ad3958
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Driver/KeyScanEventArgs.cs
@@ -0,0 +1,19 @@
+using System;
+
+namespace Meadow.Foundation.ICs.IOExpanders
+{
+ public class KeyScanEventArgs : EventArgs
+ {
+ public As1115.KeyScanButtonType Button { get; protected set; }
+
+ public byte KeyA { get; protected set; }
+ public byte KeyB { get; protected set; }
+
+ public KeyScanEventArgs(As1115.KeyScanButtonType button, byte keyA, byte keyB)
+ {
+ Button = button;
+ KeyA = keyA;
+ KeyB = keyB;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Samples/As1115_Sample/As1115_Sample.csproj b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Samples/As1115_Sample/As1115_Sample.csproj
new file mode 100644
index 0000000000..c4074adc18
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Samples/As1115_Sample/As1115_Sample.csproj
@@ -0,0 +1,15 @@
+
+
+ https://github.com/WildernessLabs/Meadow.Foundation
+ Wilderness Labs, Inc
+ Wilderness Labs, Inc
+ true
+ netstandard2.1
+ Library
+ App
+
+
+
+
+
+
diff --git a/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Samples/As1115_Sample/MeadowApp.cs b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Samples/As1115_Sample/MeadowApp.cs
new file mode 100644
index 0000000000..58a59792ba
--- /dev/null
+++ b/Source/Meadow.Foundation.Peripherals/ICs.IOExpanders.As1115/Samples/As1115_Sample/MeadowApp.cs
@@ -0,0 +1,62 @@
+using Meadow;
+using Meadow.Devices;
+using Meadow.Foundation.Graphics;
+using Meadow.Foundation.ICs.IOExpanders;
+using System;
+using System.Threading.Tasks;
+using static Meadow.Foundation.ICs.IOExpanders.As1115;
+
+namespace ICs.IOExpanders.As1115_Sample
+{
+ public class MeadowApp : App
+ {
+ //
+
+ As1115 as1115;
+ MicroGraphics graphics;
+
+ public override Task Initialize()
+ {
+ Console.WriteLine("Initialize...");
+ as1115 = new As1115(Device, Device.CreateI2cBus(), Device.Pins.D03);
+
+ //general key scan events - will raise for all buttons
+ as1115.KeyScanPressStarted += KeyScanPressStarted;
+
+ //or access buttons as IButtons individually
+ as1115.KeyScanButtons[KeyScanButtonType.Button1].LongClickedThreshold = TimeSpan.FromSeconds(1);
+ as1115.KeyScanButtons[KeyScanButtonType.Button1].Clicked += Button1_Clicked;
+ as1115.KeyScanButtons[KeyScanButtonType.Button1].LongClicked += Button1_LongClicked; ;
+
+ graphics = new MicroGraphics(as1115);
+
+ return base.Initialize();
+ }
+
+ private void Button1_LongClicked(object sender, EventArgs e)
+ {
+ Console.WriteLine("Button 1 long press");
+ }
+
+ private void Button1_Clicked(object sender, EventArgs e)
+ {
+ Console.WriteLine("Button 1 clicked");
+ }
+
+ private void KeyScanPressStarted(object sender, KeyScanEventArgs e)
+ {
+ Console.WriteLine($"{e.Button} pressed");
+ }
+
+ public override async Task Run()
+ {
+ graphics.Clear();
+ graphics.DrawLine(0, 0, 7, 7, true);
+ graphics.DrawLine(0, 7, 7, 0, true);
+
+ graphics.Show();
+ }
+
+ //
+ }
+}
\ No newline at end of file
diff --git a/Source/Meadow.Foundation.sln b/Source/Meadow.Foundation.sln
index e272dd3310..f434ef066a 100644
--- a/Source/Meadow.Foundation.sln
+++ b/Source/Meadow.Foundation.sln
@@ -1130,6 +1130,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sw18AB_ADC_Sample", "Meadow
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sw18AB_Ultrasonic_Sample", "Meadow.Foundation.Peripherals\ICs.IOExpanders.SerialWombat\Samples\Sw18AB_Ultrasonic_Sample\Sw18AB_Ultrasonic_Sample.csproj", "{B8578827-6DB4-491A-87B0-36D95AE008D3}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ICs.IOExpanders.As1115", "ICs.IOExpanders.As1115", "{2A780BB9-6C85-41A9-98F1-8B13B5C54093}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{1C955941-ADF9-478A-B17C-24C5F6434E40}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICs.IOExpanders.As1115", "Meadow.Foundation.Peripherals\ICs.IOExpanders.As1115\Driver\ICs.IOExpanders.As1115.csproj", "{0F796184-BC8F-4C32-8EC4-EF13D1229D4A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "As1115_Sample", "Meadow.Foundation.Peripherals\ICs.IOExpanders.As1115\Samples\As1115_Sample\As1115_Sample.csproj", "{6F6C93D0-2FBB-4633-BEDA-4F194625C098}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -2584,6 +2592,18 @@ Global
{B8578827-6DB4-491A-87B0-36D95AE008D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B8578827-6DB4-491A-87B0-36D95AE008D3}.Release|Any CPU.Build.0 = Release|Any CPU
{B8578827-6DB4-491A-87B0-36D95AE008D3}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {0F796184-BC8F-4C32-8EC4-EF13D1229D4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0F796184-BC8F-4C32-8EC4-EF13D1229D4A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0F796184-BC8F-4C32-8EC4-EF13D1229D4A}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {0F796184-BC8F-4C32-8EC4-EF13D1229D4A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0F796184-BC8F-4C32-8EC4-EF13D1229D4A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0F796184-BC8F-4C32-8EC4-EF13D1229D4A}.Release|Any CPU.Deploy.0 = Release|Any CPU
+ {6F6C93D0-2FBB-4633-BEDA-4F194625C098}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6F6C93D0-2FBB-4633-BEDA-4F194625C098}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6F6C93D0-2FBB-4633-BEDA-4F194625C098}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
+ {6F6C93D0-2FBB-4633-BEDA-4F194625C098}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6F6C93D0-2FBB-4633-BEDA-4F194625C098}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6F6C93D0-2FBB-4633-BEDA-4F194625C098}.Release|Any CPU.Deploy.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -3146,6 +3166,10 @@ Global
{71290423-6A82-4263-B592-8266EAB58D9B} = {5F4B9D7E-81B4-4562-BEDC-3499A8DDE648}
{E15DD562-8ED5-4311-BE65-DEA0DB592FB2} = {5F4B9D7E-81B4-4562-BEDC-3499A8DDE648}
{B8578827-6DB4-491A-87B0-36D95AE008D3} = {5F4B9D7E-81B4-4562-BEDC-3499A8DDE648}
+ {2A780BB9-6C85-41A9-98F1-8B13B5C54093} = {86B81B21-8C90-4A99-B113-FA71F8A6CD8D}
+ {1C955941-ADF9-478A-B17C-24C5F6434E40} = {2A780BB9-6C85-41A9-98F1-8B13B5C54093}
+ {0F796184-BC8F-4C32-8EC4-EF13D1229D4A} = {2A780BB9-6C85-41A9-98F1-8B13B5C54093}
+ {6F6C93D0-2FBB-4633-BEDA-4F194625C098} = {1C955941-ADF9-478A-B17C-24C5F6434E40}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AF7CA16F-8C38-4546-87A2-5DAAF58A1520}