Quelltext /~heha/ewa/Motor/Maxmaus12.zip/usbd.h

// USB-Gerät: Maus + CDC + WebUSB
#pragma once
#include <stdint.h>		// uint32_t
// Nur bei C28, nicht bei CM:
typedef uint16_t uint8_t;
typedef int16_t int8_t;

//extern uint8_t&__byte(int*,int);
//#include <inc/hw_types.h>	// uint8_t
//#include <inc/hw_memmap.h>	// USBA_BASE

namespace usb{

const uint32_t BASE = 0x40000;

struct Regs{//C28-View, nicht CM-View! Nur Device, nicht Host!
  class byte{
    uint16_t b;
public:
    inline operator unsigned() const volatile {return __byte((int*)this,0);}
    inline void operator=(unsigned v) volatile {__byte((int*)this,0)=v;}
    inline void operator|=(unsigned v) volatile {__byte((int*)this,0)|=v;}
    inline void operator&=(unsigned v) volatile {__byte((int*)this,0)&=v;}
  };
  class word{
    uint16_t w,h;
public:
    inline operator unsigned() const volatile {return w;}
    inline void operator=(unsigned v) volatile {w=v;}
    inline void operator|=(unsigned v) volatile {w|=v;}
    inline void operator&=(unsigned v) volatile {w&=v;}
  };
  class dword{
    uint32_t w,h;
  public:
    inline operator uint32_t() const volatile {return w;}
    inline void operator=(uint32_t v) volatile {w=v;}
  };
  byte FADDR;
  byte POWER;
  word TXIS,RXIS;
  word TXIE,RXIE;
  byte IS,IE;
  word FRAME;
  byte EPIDX,TEST;
  byte rsv10[16];
  union{	// Offset 0x20
   byte b;
   word w;
   dword dw;
  }FIFO[16];
  byte DEVCTL,rsv61;	// Offset 0x60
  byte TXFIFOSZ,RXFIFOSZ;	// EPIDX selects endpoint
  word TXFIFOADDR,RXFIFOADDR;	// EPIDX selects endpoint
  word rsv68[9];
  byte CONTIM,rsv7b,rsv7c,FSEOF,LSEOF,rsv7f;
  byte rsv80[128];
  union{
    struct{
      word rsv100,CSR,rsv104[2],COUNT;
    };
    struct{
      word TXMAXP;
      word TXCSR;	// ep0: CSRL, CSRH
      word RXMAXP;
      byte RXCSRL,RXCSRH;
      word RXCOUNT,rsv10a[3];	// ep0: COUNT
   }ep[16];
  };
  byte rsv[0x140];
  word RXDPKTBUFDIS,TXDPKTBUFDIS;
  byte rsv344[0xBC];
  dword EPC,EPCRIS,EPCIM,EPCISC;
  dword DRRIS,DRIM,DRISC,GPCS;
  dword rsv420[12];
  dword DMASEL;
};

extern volatile Regs RegsA;

// USB-Request als Byte-struct erspart Alignment-Probleme
struct tRequest{
  uint8_t bmRequestType,// Determines the type and direction of the request.
  bRequest,		// Identifies the specific request being made.
  wValueL, wValueH,	// Word-sized field that varies according to the request.
  wIndexL, wIndexH,	// Word-sized field that varies according to the request.
  wLengthL, wLengthH;	// The number of bytes to transfer if there is a data stage to the request.
  uint16_t wRequest() const {return bRequest<<8|bmRequestType;}
  uint16_t wValue() const {return wValueH<<8|wValueL;}
  uint16_t wIndex() const {return wIndexH<<8|wIndexL;}
  uint16_t wLength() const {return wLengthH<<8|wLengthL;}
  void limitLength(unsigned&l) const {if (l>wLength()) l=wLength();}
  void limitLength(volatile unsigned&l) const {if (l>wLength()) l=wLength();}
  operator uint8_t*() {return &bmRequestType;}
};

// Generate two-byte, three-byte, and four-byte value for USB descriptors
#define USB2(v)  (v) & 0xff, (v) >> 8
#define USB3(v)  USB2((v)&0xFFFF), (v)>> 16
#define USB4(v)  USB2((v)&0xFFFF), USB2((v)>>16)

struct tDevice {
  virtual ~tDevice() {}
  virtual void idle() {}
  virtual bool cbGetDescriptor(const tRequest&)		{return false;}
  virtual bool cbRequestHandler(const tRequest&)	{return false;}
  virtual void onReset()		{devstat &= ~2;	config=0;}
  virtual void onDisconnect()		{onReset();}
  virtual void onSOF()			{}
  uint8_t config;	// 0 = unconfigured, 1 = configured
  uint8_t devstat;	// Bit 0: SelfPower, Bit 1: RemoteWakeupEnabled

  // USB-Peripheriefreigabe, Taktung und GPIO müssen vorher eingestellt werden.
  // Interrupts und DMA werden nicht benötigt
  bool Init();
  void Term();
  bool SendDataEP0(const uint8_t*,unsigned, const tRequest&,bool=false);
  // synchron, kehrt bei Abarbeitung aller Bytes zurück, ruft idle() wenn zu warten ist
  // liefert false nur wenn etwas katastrophales wie USB-Busreset dazwischenfunkt, sonst stets true
  void PowerStatusSet(bool selfpower) {if (selfpower) devstat|=1; else devstat&=~1;}
  // zyklisch aufzurufen, erspart Interrupts (die mit wichtigeren Dingen beschäftigt sind)
  void poll();
private:
  void pollEP0();
  bool SendDataEP0(const uint8_t*,unsigned,bool=false);
};

#pragma diag_suppress 2827	// override is C++11
struct tMyDevice:public tDevice{
// Nur für Interface 0 = Maus
  bool StateChange(uint8_t ui8Buttons, int8_t i8DeltaX,int8_t i8DeltaY);
private:
  bool SendReport(uint8_t *pi8Data, unsigned len);	// hier: len <= 64!
  uint8_t inrep[3];
  virtual bool cbRequestHandler(const tRequest&) override;
  virtual bool cbGetDescriptor(const tRequest&rq) override;
};
}
Vorgefundene Kodierung: UTF-80