// 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;
};
}
Detected encoding: UTF-8 | 0
|