Question

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.

Était-ce utile?

La solution

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>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top