This commit is contained in:
pelikhan 2022-01-11 06:26:41 -08:00
Родитель 581adeca68
Коммит 06c465ba49
14 изменённых файлов: 299 добавлений и 44 удалений

Просмотреть файл

@ -44,6 +44,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{079F
EndProject
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "Jacdac.Nano", "Jacdac.Nano\Jacdac.Nano.nfproj", "{071C8FF7-00A1-4C77-9192-146C24327E8B}"
EndProject
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "Jacdac.Nano.Transports.Spi", "Jacdac.Nano.Transports.Spi\Jacdac.Nano.Transports.Spi.nfproj", "{7D0D9C8B-9E8F-475A-B32C-9038C714A19B}"
EndProject
Project("{11A8DD76-328B-46DF-9F39-F559912D0360}") = "Jacdac.Nano.Clients", "Jacdac.Nano.Clients\Jacdac.Nano.Clients.nfproj", "{3807D02E-87C6-4A3D-85DD-FA3ADB573A5C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -118,6 +122,18 @@ Global
{071C8FF7-00A1-4C77-9192-146C24327E8B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{071C8FF7-00A1-4C77-9192-146C24327E8B}.Release|Any CPU.Build.0 = Release|Any CPU
{071C8FF7-00A1-4C77-9192-146C24327E8B}.Release|Any CPU.Deploy.0 = Release|Any CPU
{7D0D9C8B-9E8F-475A-B32C-9038C714A19B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7D0D9C8B-9E8F-475A-B32C-9038C714A19B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7D0D9C8B-9E8F-475A-B32C-9038C714A19B}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{7D0D9C8B-9E8F-475A-B32C-9038C714A19B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7D0D9C8B-9E8F-475A-B32C-9038C714A19B}.Release|Any CPU.Build.0 = Release|Any CPU
{7D0D9C8B-9E8F-475A-B32C-9038C714A19B}.Release|Any CPU.Deploy.0 = Release|Any CPU
{3807D02E-87C6-4A3D-85DD-FA3ADB573A5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3807D02E-87C6-4A3D-85DD-FA3ADB573A5C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3807D02E-87C6-4A3D-85DD-FA3ADB573A5C}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
{3807D02E-87C6-4A3D-85DD-FA3ADB573A5C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3807D02E-87C6-4A3D-85DD-FA3ADB573A5C}.Release|Any CPU.Build.0 = Release|Any CPU
{3807D02E-87C6-4A3D-85DD-FA3ADB573A5C}.Release|Any CPU.Deploy.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

Просмотреть файл

@ -1,8 +1,7 @@
using System;
using System.Collections.Concurrent;
using System.Collections;
using System.Device.Gpio;
using System.Device.Spi;
using System.Diagnostics;
using System.Threading;
namespace Jacdac.Transports.Spi
@ -26,8 +25,63 @@ namespace Jacdac.Transports.Spi
readonly int spiBusId;
readonly GpioController controller;
SpiDevice spi;
readonly ConcurrentQueue<byte[]> sendQueue;
readonly ConcurrentQueue<byte[]> receiveQueue;
// must be synched with sendQueue
readonly Queue sendQueue;
// must be synched with receiveQueue
readonly Queue receiveQueue;
static class QueueExtensions
{
public static bool TryDequeue(Queue queue, out byte[] value)
{
lock (queue)
{
if (queue.Count > 0)
{
value = (byte[])queue.Dequeue();
return true;
}
else
{
value = null;
return false;
}
}
}
public static bool TryPeekAndDequeue(Queue queue, int maxLength, out byte[] value)
{
lock (queue)
{
if (queue.Count > 0)
{
value = (byte[])queue.Peek();
if (value.Length <= maxLength)
{
queue.Dequeue();
return true;
}
}
value = null;
return false;
}
}
public static bool IsEmpty(Queue queue)
{
lock (queue)
{
return queue.Count == 0;
}
}
public static void Enqueue(Queue queue, byte[] value)
{
lock (queue)
queue.Enqueue(value);
}
}
public static SpiTransport Create()
{
@ -43,8 +97,8 @@ namespace Jacdac.Transports.Spi
this.rxReadyPin = rxReadyPin;
this.resetPin = resetPin;
this.spiBusId = spiBusId;
this.sendQueue = new ConcurrentQueue<byte[]>();
this.receiveQueue = new ConcurrentQueue<byte[]>();
this.sendQueue = new Queue();
this.receiveQueue = new Queue();
}
public override string ToString()
@ -106,7 +160,7 @@ namespace Jacdac.Transports.Spi
public override void SendFrame(byte[] data)
{
//Console.WriteLine($"send frame {HexEncoding.ToString(data)}");
this.sendQueue.Enqueue(data);
QueueExtensions.Enqueue(this.sendQueue, data);
this.transfer();
}
@ -128,12 +182,9 @@ namespace Jacdac.Transports.Spi
bool transfer = true;
while (transfer)
{
lock (this.sendQueue)
{
transfer = this.transferFrame();
}
transfer = this.transferFrame();
byte[] recv;
while (this.receiveQueue.TryDequeue(out recv))
while (QueueExtensions.TryDequeue(this.receiveQueue, out recv))
{
var ev = this.FrameReceived;
if (ev != null)
@ -147,7 +198,7 @@ namespace Jacdac.Transports.Spi
// much be in a locked context
bool txReady = this.controller.Read(this.txReadyPin) == PinValue.High;
bool rxReady = this.controller.Read(this.rxReadyPin) == PinValue.High;
bool sendtx = this.sendQueue.Count > 0 && txReady;
bool sendtx = txReady && !QueueExtensions.IsEmpty(this.sendQueue) && txReady;
if (!sendtx && !rxReady)
return false;
@ -159,13 +210,15 @@ namespace Jacdac.Transports.Spi
// assemble packets into send buffer
int txq_ptr = 0;
byte[] pkt;
while (this.sendQueue.TryPeek(out pkt) && txq_ptr + pkt.Length < XFER_SIZE)
while (QueueExtensions.TryPeekAndDequeue(this.sendQueue, (int)(XFER_SIZE - txq_ptr), out pkt))
{
this.sendQueue.TryDequeue(out pkt);
Array.Copy(pkt, 0, txqueue, txq_ptr, pkt.Length);
txq_ptr += (pkt.Length + 3) & ~3;
}
if (txq_ptr == 0 && !rxReady)
return false; // nothing to transfer, nothing to receive
// attempt transfer
var ok = this.attemptTransferBuffers(txqueue, rxqueue);
if (!ok)
@ -182,13 +235,6 @@ namespace Jacdac.Transports.Spi
while (framep < XFER_SIZE)
{
var frame2 = rxqueue[framep + 2];
/*
if (framep == 0 && frame2 > 0)
{
Console.WriteLine($"tx {txReady}, rx {rxReady}, send {this.sendQueue.Count}, recv {this.receiveQueue.Count}");
Console.WriteLine($"rx {HexEncoding.ToString(rxqueue)}");
}
*/
if (frame2 == 0)
break;
int sz = frame2 + 12;
@ -210,7 +256,7 @@ namespace Jacdac.Transports.Spi
var frame = new byte[sz];
Array.Copy(rxqueue, framep, frame, 0, sz);
//Console.WriteLine($"recv frame {HexEncoding.ToString(frame)}");
this.receiveQueue.Enqueue(frame);
QueueExtensions.Enqueue(this.receiveQueue, frame);
}
sz = (sz + 3) & ~3;
framep += sz;
@ -231,7 +277,7 @@ namespace Jacdac.Transports.Spi
}
catch (Exception ex)
{
Console.WriteLine(ex);
Console.WriteLine(ex.Message);
Thread.Sleep(1);
}
}
@ -242,10 +288,7 @@ namespace Jacdac.Transports.Spi
{
var err = this.ErrorReceived;
if (err != null)
{
var now = DateTime.Now;
err(this, new TransportErrorReceivedEventArgs(error, now, data));
}
err(this, new TransportErrorReceivedEventArgs(error, data));
}
}
}

Просмотреть файл

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<NanoFrameworkProjectSystemPath>$(MSBuildExtensionsPath)\nanoFramework\v1.0\</NanoFrameworkProjectSystemPath>
</PropertyGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectTypeGuids>{11A8DD76-328B-46DF-9F39-F559912D0360};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<ProjectGuid>3807d02e-87c6-4a3d-85dd-fa3adb573a5c</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<FileAlignment>512</FileAlignment>
<RootNamespace>Jacdac.Nano.Clients</RootNamespace>
<AssemblyName>Jacdac.Nano.Clients</AssemblyName>
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.props')" />
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="mscorlib">
<HintPath>..\packages\nanoFramework.CoreLibrary.1.11.7\lib\mscorlib.dll</HintPath>
</Reference>
<Reference Include="System.Math">
<HintPath>..\packages\nanoFramework.System.Math.1.4.3\lib\System.Math.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Jacdac\Clients\*.cs">
<Link>Clients\%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Jacdac.Nano\Jacdac.Nano.nfproj" />
</ItemGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets')" />
<ProjectExtensions>
<ProjectCapabilities>
<ProjectConfigurationsDeclaredAsItems />
</ProjectCapabilities>
</ProjectExtensions>
</Project>

Просмотреть файл

@ -0,0 +1,39 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("CSharp.BlankApplication")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CSharp.BlankApplication")]
[assembly: AssemblyCopyright("Copyright © ")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
/////////////////////////////////////////////////////////////////
// This attribute is mandatory when building Interop libraries //
// update this whenever the native assembly signature changes //
[assembly: AssemblyNativeVersion("1.0.0.0")]
/////////////////////////////////////////////////////////////////

Просмотреть файл

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="nanoFramework.CoreLibrary" version="1.11.7" targetFramework="netnanoframework10" />
<package id="nanoFramework.System.Math" version="1.4.3" targetFramework="netnanoframework10" />
</packages>

Просмотреть файл

@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<NanoFrameworkProjectSystemPath>$(MSBuildExtensionsPath)\nanoFramework\v1.0\</NanoFrameworkProjectSystemPath>
</PropertyGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.Default.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectTypeGuids>{11A8DD76-328B-46DF-9F39-F559912D0360};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<ProjectGuid>7d0d9c8b-9e8f-475a-b32c-9038c714a19b</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<FileAlignment>512</FileAlignment>
<RootNamespace>Jacdac.Nano.Transports.Spi</RootNamespace>
<AssemblyName>Jacdac.Nano.Transports.Spi</AssemblyName>
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.props')" />
<ItemGroup>
<Compile Include="..\Jacdac.NET.Transports.Spi\SpiTransport.cs">
<Link>SpiTransport.cs</Link>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Reference Include="mscorlib">
<HintPath>..\packages\nanoFramework.CoreLibrary.1.11.7\lib\mscorlib.dll</HintPath>
</Reference>
<Reference Include="nanoFramework.Runtime.Events">
<HintPath>..\packages\nanoFramework.Runtime.Events.1.9.2\lib\nanoFramework.Runtime.Events.dll</HintPath>
</Reference>
<Reference Include="nanoFramework.System.Collections">
<HintPath>..\packages\nanoFramework.System.Collections.1.3.0\lib\nanoFramework.System.Collections.dll</HintPath>
</Reference>
<Reference Include="System.Device.Gpio">
<HintPath>..\packages\nanoFramework.System.Device.Gpio.1.0.2\lib\System.Device.Gpio.dll</HintPath>
</Reference>
<Reference Include="System.Device.Spi">
<HintPath>..\packages\nanoFramework.System.Device.Spi.1.0.2\lib\System.Device.Spi.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Jacdac.Nano\Jacdac.Nano.nfproj" />
</ItemGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.CSharp.targets')" />
<ProjectExtensions>
<ProjectCapabilities>
<ProjectConfigurationsDeclaredAsItems />
</ProjectCapabilities>
</ProjectExtensions>
</Project>

Просмотреть файл

@ -0,0 +1,39 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("CSharp.BlankApplication")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("CSharp.BlankApplication")]
[assembly: AssemblyCopyright("Copyright © ")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
/////////////////////////////////////////////////////////////////
// This attribute is mandatory when building Interop libraries //
// update this whenever the native assembly signature changes //
[assembly: AssemblyNativeVersion("1.0.0.0")]
/////////////////////////////////////////////////////////////////

Просмотреть файл

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="nanoFramework.CoreLibrary" version="1.11.7" targetFramework="netnanoframework10" />
<package id="nanoFramework.Runtime.Events" version="1.9.2" targetFramework="netnanoframework10" />
<package id="nanoFramework.System.Collections" version="1.3.0" targetFramework="netnanoframework10" />
<package id="nanoFramework.System.Device.Gpio" version="1.0.2" targetFramework="netnanoframework10" />
<package id="nanoFramework.System.Device.Spi" version="1.0.2" targetFramework="netnanoframework10" />
</packages>

Просмотреть файл

@ -15,6 +15,7 @@
<RootNamespace>Jacdac.Nano</RootNamespace>
<AssemblyName>Jacdac.Nano</AssemblyName>
<TargetFrameworkVersion>v1.0</TargetFrameworkVersion>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<Import Project="$(NanoFrameworkProjectSystemPath)NFProjectSystem.props" Condition="Exists('$(NanoFrameworkProjectSystemPath)NFProjectSystem.props')" />
<ItemGroup>

Просмотреть файл

@ -42,7 +42,7 @@ namespace Jacdac.Transports
{
this.controller.ErrorReceived += (JacdacSerialWireController sender, ErrorReceivedEventArgs args) =>
{
value(this, new TransportErrorReceivedEventArgs((TransportError)(uint)args.Error, args.Timestamp, args.Data));
value(this, new TransportErrorReceivedEventArgs((TransportError)(uint)args.Error, args.Data));
};
}
remove

Просмотреть файл

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Jacdac.Clients
{

Просмотреть файл

@ -93,7 +93,7 @@ namespace Jacdac
this.pos = 0;
this.currcmd = 0;
this.source = source;
this.args = new System.Collections.ArrayList();
this.args = new ArrayList();
for (int i = 0; i < args.Length; i++)
this.args.Add(args[i]);
}

Просмотреть файл

@ -44,14 +44,11 @@ namespace Jacdac
public sealed class TransportErrorReceivedEventArgs
{
public TransportError Error { get; }
public DateTime Timestamp { get; }
public byte[] Data { get; }
public TransportErrorReceivedEventArgs(TransportError error, DateTime timestamp, byte[] data)
public TransportErrorReceivedEventArgs(TransportError error, byte[] data)
{
this.Error = error;
this.Timestamp = timestamp;
this.Data = data;
}
}

Просмотреть файл

@ -4,7 +4,7 @@
for **microcontrollers** and their peripherals (sensors/actuators),
with applications to rapid prototyping, making, and physical computing.
This repository contains **.NET 5+** and **TinyCLR** client libraries for the [Jacdac](https://aka.ms/jacdac) protocol,
This repository contains **.NET Core (5+)**, **.NET nanoframework** and **TinyCLR** client libraries for the [Jacdac](https://aka.ms/jacdac) protocol,
as well as transports over USB, SPI, WebSockets.
* **[Jacdac .NET Documentation](https://microsoft.github.io/jacdac-docs/clients/dotnet)**
@ -17,9 +17,9 @@ as well as transports over USB, SPI, WebSockets.
The Jacdac project contains C# sources of the Jacdac protocol for various .NET runtime, including desktop or TinyClR.
To avoid mscorlib issues, each platform recompiles these sources into its own assembly where C# files are simply shared as links.
As a result, the C# used in the Jacdac project is .NET micro framework/TinyCLR/.NET5 compatible (and also inherits limitations thereof).
As a result, the C# used in the Jacdac project is .NET 5+/.NET nanoframework/TinyCLR compatible (and also inherits limitations thereof).
### .NET 5+
### [.NET Core](https://docs.microsoft.com/en-us/dotnet/core/introduction) and [.NET IoT Core](https://dotnet.microsoft.com/en-us/apps/iot)
- `Jacdac.NET`, core runtime
- `Jacdac.NET.Clients`, service clients
@ -27,17 +27,23 @@ As a result, the C# used in the Jacdac project is .NET micro framework/TinyCLR/.
- `Jacdac.NET.Transports.WebSockets`, WebSocket transport
- `Jacdac.NET.Transports.Usb`, Usb transport, .NET5
- `Jacdac.NET.Transports.Hf2`, HF2 protocol layer, .NET5
- `Jacdac.NET.DevTools`, a web site/proxy to help with developing Jacdac applications
- `Jacdac.Tests`, unit tests, .NET6
### TinyCLR
### [TinyCLR](https://www.ghielectronics.com/tinyclr/)
- `Jacdac.TinyCLR`, mirror of `Jacdac` library and UART transport
- `Jacdac.TinyCLR.Clients`, service clients
- `Jacdac.TinyCLR.Storage`, SD card storage support
### [.NET nanoframework](https://www.nanoframework.net/)
- `Jacdac.Nano`, mirror of `Jacdac` library and UART transport
- `Jacdac.Nano.Transports.Spi`, SPI transport layer for SPI Jacdapter using .NET nanoframework
- `Jacdac.Nano.Clients`, service clients
### Misc:
- `Jacdac.NET.DevTools`, a .NET Core web site/proxy to help with developing Jacdac applications
- `Jacdac.Tests`, unit tests, .NET6
- `Jacdac`, C# Jacdac sources. This package serves as a placeholder for C# files and
and is not referenced anywhere. **For development purposes only**.