Examples

This example shows how to create a simple SpaceWire Router and a Grspw2 device and connect them.

import BusModels
import TEMUGrspw2
object-create class=Grspw2 name=grspw0
object-create class=SpwRouter name=spwRouter
spw-connect port1=grspw0:SpwPortIface[0] port2=spwRouter:SpwPortIface[0]

The next example shows how to implement a simple SpaceWire device

#include <stdint.h>
#include <stdio.h>
#include <string.h>

#include "temu-c/Support/Objsys.h"
#include "temu-c/Support/Attributes.h"
#include "temu-c/Support/Logging.h"
#include "temu-c/Bus/Spacewire.h"

typedef struct {
  temu_Object Super;

  int TransmitterDataRate;
  temu_SpwLinkState LinkState;
  temu_SpwPortIfaceRef Uplink;
} SpwDevice;

void*
create(const char *Name,
       int Argc TEMU_UNUSED,
       const temu_CreateArg *Argv TEMU_UNUSED)
{
  void *Obj = malloc(sizeof(SpwDevice));
  memset(Obj, 0, sizeof(SpwDevice));

  printf("Creating Object '%s'\n", Name);

  return Obj;
}

void
destroy(void *Obj)
{
  free(Obj);
}

static void
spwDeviceChangeLinkState(SpwDevice *Device, temu_SpwLinkState LinkState)
{
  Device->LinkState = LinkState;
  if ((Device->Uplink.Iface != NULL) && (Device->Uplink.Obj != NULL)) {
      Device->Uplink.Iface->signalLinkStateChange(
        Device->Uplink.Obj, LinkState);
  }
}

///////////////////////////////////////////////////////////////////////////////
// SpwPortIface 0 implementation
///////////////////////////////////////////////////////////////////////////////

static void
spwPortIfaceReceive0(void *Obj, void *Sender, temu_SpwPacket *Pkt)
{
  // Handle packet received.
  SpwDevice *Dev = (SpwDevice*)(Obj);
  temu_logInfo(Dev, "Received SpaceWire packet");
}

static void
spwPortIfaceSignalLinkStateChange0(void *Obj, temu_SpwLinkState LinkState)
{
  // The other side notified us that its link state changed.
  SpwDevice *Dev = (SpwDevice*)(Obj);
  temu_logInfo(Dev, "Other side link state changed");

  // Depending on the other side link state change update this
  // device link state.
}

static temu_SpwLinkState
spwPortIfaceGetOtherSideLinkState0(void *Obj)
{
  // Other side request this device state.
  SpwDevice *Dev = (SpwDevice*)(Obj);
  return (temu_SpwLinkState)Dev->LinkState;
}

static void
spwPortIfaceConnect0(void *Obj, temu_SpwPortIfaceRef PortIf)
{
  SpwDevice *Dev = (SpwDevice*)(Obj);
  Dev->Uplink = PortIf;

  // When two ports are connected the device goes to ready state.
  spwDeviceChangeLinkState(Dev, teSPWLS_Ready);
}

static void
spwPortIfaceDisconnect0(void *Obj)
{
  SpwDevice *Dev = (SpwDevice*)(Obj);
  Dev->Uplink.Iface = NULL;
  Dev->Uplink.Obj = NULL;

  // When two ports are diconnected the device goes to error reset state.
  spwDeviceChangeLinkState(Dev, teSPWLS_ErrorReset);
}

static uint64_t
spwPortIfaceTimeToSendPacketNs0(void* Obj, uint64_t PacketSize)
{
  SpwDevice *Dev = (SpwDevice*)(Obj);
  // Return the time required to transmit the packet through this port.
  return PacketSize / Dev->TransmitterDataRate;
}

temu_SpwPortIface SpwPortIface0 = {
  spwPortIfaceReceive0,
  spwPortIfaceSignalLinkStateChange0,
  spwPortIfaceGetOtherSideLinkState0,
  spwPortIfaceConnect0,
  spwPortIfaceDisconnect0,
  spwPortIfaceTimeToSendPacketNs0
};

TEMU_PLUGIN_INIT
{
  temu_Class *Cls = temu_registerClass("SpwDevice", create, destroy);

  // Reference to the port interface of the other end.
  temu_addProperty(Cls, "Uplink",
                   offsetof(SpwDevice, Uplink),
                   teTY_IfaceRef,
                   1, // Number of elements (1 = scalar)
                   NULL, NULL,
                   "Other end port interface");

  // Port interface.
  temu_addInterface(Cls, "SpwPortIface", "SpwPortIface", &SpwPortIface0,
                    0, "SpaceWire port interface");
}