Frage

In a new design (new to .NET Micro) I have a series of LED 7 segment displays which are controlled via the SPI bus with Netduino.

Now, I have seen that one doesn't have to emulate the SPI bus stuff because the .NET Microframework already has an emulated SPI bus, fantastic.

Since my "module" is controlled by SPI I would like to abstract it via SPIDevice and SPIBus, but I have scoured all over the internet and have not been able to find a single example of how to roll your own custom SPIDevice (and control it) for use in a .NET MF DeviceEmulator project.

Basically in my SPIDevice I will have a series of controll registers plus the data for each of the LEDs but I am in desperate need for an example that can lead the way into the right direction. When I installed the .NET MF 4.3 it did not install any samples.

War es hilfreich?

Lösung

An option might be to use aggregation to achieve what you are looking for.

For example, you could create a class called SevenSegmentDisplay which exposes methods/properties to interact with the 7 segment LED module and wraps a private SPI instance. Internally the methods call to the private SPI instance to actually communicate with the physical device.

For the emulator, here is the code + config I wrote for a flash memory chip which has an SPI interface. This was used for internal testing while waiting for the physical device.

using System;
using Microsoft.SPOT.Emulator;
using Microsoft.SPOT.Emulator.Spi;
using System.Diagnostics;

namespace dotnetwarrior.Emulator.Hardware
{
  class MX25l3206FlashMemory : SpiDevice
  {
    private byte[] _memory;

    public int MemorySize { get; set; }
    public int SectorSize { get; set; }
    public int PageSize { get; set; }

    private Status _status;

    [Flags]
    enum Status
    {
      Wip = 1,
      Wel = 2,
      Bp0 = 4,
      Bp1 = 8,
      Bp2 = 16,
      E_Err = 32,
      P_Err = 64,
      SRWD = 128
    }

    public MX25l3206FlashMemory()
    {     
    }

    public byte GetByte(int address)
    {
      return _memory[address];
    }

    public override void SetupComponent()
    {
      base.SetupComponent();
      _memory = new byte[MemorySize];
    }

    protected override byte[] Write(byte[] data)
    {
      switch (data[0])
      {
        case 0x03: return Read(data);
        case 0x9f: return ReadIdentification(data);
        case 0x90: return ReadManufacturer(data);
        case 0x06: return WriteEnable(data);
        case 0x04: return WriteDisable(data);
        case 0x20: return Erase4K(data);
        case 0x40: return Erase8K(data);
        case 0xd8: return EraseSector(data);
        case 0x60:
        case 0xC7: return EraseDevice(data);
        case 0x02: return PagePrograme(data);
        case 0x05: return ReadStatus(data);
        case 0x01: return WriteStatus(data);
        case 0x35: return ReadConfig(data);        
      }
      throw new NotImplementedException("Unexpected Flash command : " + data[0].ToString());
    }

    private int GetAddress(byte[] data)
    {
      byte[] address = new byte[4];
      Buffer.BlockCopy(data, 1, address, 1, 3);
      Array.Reverse(address);
      return (BitConverter.ToInt32(address, 0) % MemorySize);
    }

    private byte[] Read(byte[] data)
    {
      int address = GetAddress(data);
      Buffer.BlockCopy(_memory, address, data, 4, data.Length - 4);
      return data;      
    }

    private byte[] ReadIdentification(byte[] data)
    {
      return new byte[]{0x01, 0x02, 0x15, 0x4d};
    }

    private byte[] ReadManufacturer(byte[] data)
    {
      return new byte[]{0x01, 0x02};
    }

    private byte[] WriteEnable(byte[] data)
    {
      _status |= Status.Wel;      
      return new byte[]{};
    }

    private byte[] WriteDisable(byte[] data)
    {
      _status &= ~Status.Wel;

      return new byte[]{};
    }

    private byte[] ReadStatus(byte[] data)
    {
      return new byte[] { (byte)_status, (byte)_status };
    }

    private byte[] WriteStatus(byte[] data)
    {
      _status = (Status)data[1];
      return new byte[] { };
    }

    private byte[] Erase4K(byte[] data)
    {
      if (!_status.HasFlag(Status.Wel) || _status.HasFlag(Status.Wip)) return new byte[] { };
      try
      {
        _status |= Status.Wip;

      }
      finally
      {
        _status &= ~(Status.Wel | Status.Wip);        
      }
      return new byte[] { };
    }

    private byte[] Erase8K(byte[] data)
    {
      if (!_status.HasFlag(Status.Wel) || _status.HasFlag(Status.Wip)) return new byte[] { };
      _status |= Status.Wip;
      try
      {


      }
      finally
      {
        _status &= ~(Status.Wel | Status.Wip);
      }
      return new byte[] { };
    }

    private byte[] EraseSector(byte[] data)
    {
      if (!_status.HasFlag(Status.Wel) || _status.HasFlag(Status.Wip)) return new byte[] { };
      _status |= Status.Wip;
      try
      {
        int address = GetAddress(data);
        int sector = address / SectorSize;
        int sectorStartAddress = sector * SectorSize;
        for (int i = 0; i < SectorSize; i++)
        {
          _memory[sectorStartAddress + i] = 0xff;
        }
      }
      finally
      {
        _status &= ~(Status.Wel | Status.Wip);
      }

      return new byte[] { };      
    }

    private byte[] EraseDevice(byte[] data)
    {
      if (!_status.HasFlag(Status.Wel) || _status.HasFlag(Status.Wip)) return new byte[] { };
      _status |= Status.Wip;

      try
      {
        for (int i = 0; i < MemorySize; i++)
        {
          _memory[i] = 0xff;
        }
      }
      finally
      {
        _status &= ~(Status.Wel | Status.Wip);
      }


      return new byte[] { };
    }

    private byte[] PagePrograme(byte[] data)
    {
      if (!_status.HasFlag(Status.Wel) || _status.HasFlag(Status.Wip)) return new byte[] { };
      _status |= Status.Wip;

      try
      {
        int address = GetAddress(data);
        int offset = address % PageSize;

        for (int i = 0; i < data.Length - 4; i++)
        {
          _memory[address + ((offset + i) % PageSize)] &= (byte)data[i + 4];
        }
      }
      finally
      {
        _status &= ~(Status.Wel | Status.Wip);
      }


      return new byte[] { };
    }


    private byte[] ReadConfig(byte[] data)
    {
      return new byte[] { };
    }
  }
}

The corresponding configuration to configure the flash memory into the emulator follows (Note this was used in a custom emulator).

  <Types>
    <MX25l3206>dotnetwarrior.Emulator.Hardware.MX25l3206FlashMemory, dotnetwarrior.Emulator</MX25l3206>
    <AccessIndicator>dotnetwarrior.Emulator.Hardware.AccessIndicator, dotnetwarrior.Emulator</AccessIndicator>
  </Types>

  <EmulatorComponents>
    <MX25l3206 id="myFlash">
      <MemorySize>4194304</MemorySize>
      <SectorSize>65536</SectorSize>
      <PageSize>256</PageSize>

      <ChipSelectPin>10</ChipSelectPin>      
      <!--SPI-->
      <ChipSelectActiveState>false</ChipSelectActiveState>
      <ChipSelectSetupTime>1</ChipSelectSetupTime>
      <ChipSelectHoldTime>1</ChipSelectHoldTime>
      <ClockRateKHz>36000</ClockRateKHz>
      <ClockIdleState>false</ClockIdleState>
      <ClockEdge>false</ClockEdge>
      <SpiModule>Spi1</SpiModule>
      <!--Hardware Provider-->
      <Mask>1</Mask>
      <Mosi>2</Mosi>
      <Miso>3</Miso>
    </MX25l3206>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top