#define EP0_BUFF_SIZE 16 #define MAX_PACKET_SIZE 64 #if (EP0_BUFF_SIZE+2*MAX_PACKET_SIZE) > USER_USB_RAM #error "This example needs more USB ram. Increase this setting in menu." #endif #include #include "usb_desc.h" // from https://github.com/ole00/ch554_sdcc_usb_blinky // custom USB definitions, must be set before the "usb_intr.h" is included #define USB_CUST_VENDOR_ID 0x4348 #define USB_CUST_VENDOR_NAME_LEN 7 #define USB_CUST_VENDOR_NAME {'w','c','h','.','c', 'n', 0} #define USB_CUST_PRODUCT_ID 0x5537 #define USB_CUST_PRODUCT_NAME_LEN 7 #define USB_CUST_PRODUCT_NAME { 'v', 'e', 'n', 'd', 'o', 'r', 0 } #define USB_CUST_CONF_POWER 120 #define USB_CUST_EP_COUNT 2 #define USB_CUST_EP_DEF USB_EP_DSC ep01o; USB_EP_DSC ep01i; #define USB_CUST_EP_DESC {sizeof(USB_EP_DSC), USB_DESC_EP, USB_EP01_OUT, USB_TRNT_BULK, MAX_PACKET_SIZE , 0x00}, {sizeof(USB_EP_DSC), USB_DESC_EP, USB_EP01_IN, USB_TRNT_BULK, MAX_PACKET_SIZE , 0x00} #define USB_CUST_EP_INIT initEndPoint() #define USB_CUST_EP1_IN_HANDLER handlerVendorEndPoint1in() #define USB_CUST_EP1_OUT_HANDLER handlerVendorEndPoint1out() #define USB_CUST_CONTROL_TRANSFER_HANDLER handleVendorControlTransfer() //#define USB_CUST_CONTROL_DATA_HANDLER handleVendorDataTransfer() void initEndPoint(); void handlerVendorEndPoint1in(); void handlerVendorEndPoint1out(); static uint16_t handleVendorControlTransfer(); #include "usb_intr.h" // from https://github.com/ole00/ch554_sdcc_usb_blinky and modify as below // //void DeviceUSBInterrupt(void) __interrupt(INT_NO_USB) // void USBInterrupt(void) __xdata __at (EP0_BUFF_SIZE) uint8_t Ep1outBuffer[MAX_PACKET_SIZE]; // OUT __xdata __at (EP0_BUFF_SIZE+MAX_PACKET_SIZE) uint8_t Ep1inBuffer[MAX_PACKET_SIZE]; // IN volatile __xdata uint8_t writing = false; volatile __xdata uint8_t reading = false; volatile __xdata uint8_t ready = false; // ready for in/out volatile __xdata uint8_t lngth = 0; // data length volatile __xdata uint8_t eos = 0x0a; // end of string volatile __xdata uint8_t eot = false; // end of transmission volatile __xdata uint16_t timeout=200; //200ms volatile __xdata uint16_t ttlsz=0; //total size to read #define GPIB_DIO1 32 // CH552T 1, GPIB 1 : I/O data bit 1 #define GPIB_DIO2 14 // CH552T 2, GPIB 2 : I/O data bit 2 #define GPIB_DIO3 15 // CH552T 3, GPIB 3 : I/O data bit 3 #define GPIB_DIO4 16 // CH552T 4, GPIB 4 : I/O data bit 4 #define GPIB_EOI 17 // CH552T 5, GPIB 5 : End Or Identify #define GPIB_DAV 10 // CH552T 7, GPIB 6 : DAta Valid #define GPIB_NRFD 11 // CH552T 8, GPIB 7 : Not Ready For Data #define GPIB_NDAC 31 // CH552T 9, GPIB 8 : Not Data ACcepted #define GPIB_IFC 30 // CH552T 10, GPIB 9 : InterFace Clear #define GPIB_SRQ bRST // CH552T 6, GPIB 10 : Service ReQuest #define GPIB_ATN 33 // CH552T 11, GPIB 11 : ATteNtion // shield GND //USB shield, GPIB 12 #define GPIB_DIO5 12 // CH552T 17, GPIB 13 : I/O data bit 5 #define GPIB_DIO6 13 // CH552T 16, GPIB 14 : I/O data bit 6 #define GPIB_DIO7 35 // CH552T 13, GPIB 15 : I/O data bit 7 #define GPIB_DIO8 34 // CH552T 12, GPIB 16 : I/O data bit 8 #define GPIB_REN 9 // CH552T 18, GPIB 17 : Remote ENable 9:non-existing pin // GND // CH552T 18, GPIB 18-23 // signal GND // CH552T 18, GPIB 24 // CH552 Vcc(19)-0.1uF-GND(18)-0.1uF-V33(20) // control request commands #define GPIB_EP1 0x20 #define GPIB_DIO_LINE 0x40+0 #define GPIB_EOI_LINE 0x40+5 #define GPIB_DAV_LINE 0x40+6 #define GPIB_NRFD_LINE 0x40+7 #define GPIB_NDAC_LINE 0x40+8 #define GPIB_IFC_LINE 0x40+9 #define GPIB_SRQ_LINE 0x40+10 #define GPIB_ATN_LINE 0x40+11 #define GPIB_REN_LINE 0x40+17 #define GPIB_READ 0x80 #define GPIB_WRITING 0x81 #define GPIB_READING 0x82 #define GPIB_READY 0x83 #define GPIB_LNGTH 0x84 #define GPIB_EOS 0x85 #define GPIB_EOT 0x86 #define GPIB_TIMEOUT 0x87 #define GPIB_TTLSZ 0x88 //to use RST, please set EN_RST_RESET=0 using ch55xtool. //ch55xtool -p -a Dis_RST_RESET --cfgs_options_force_action char set_num(uint8_t ch,char num){ // INPUT_PULLUP, nagative logic if(num==0){digitalWrite(ch, HIGH); return digitalRead(ch);} //high and read else {digitalWrite(ch, LOW); return 0;} //low } uint8_t readSRQ(){ __data uint8_t bit = GPIB_SRQ; __data uint8_t portBuf = CLOCK_CFG; if (portBuf & bit) return HIGH; else return LOW; } void init_GPIB(){ pinMode(GPIB_DIO1,INPUT_PULLUP); pinMode(GPIB_DIO5,INPUT_PULLUP); pinMode(GPIB_DIO2,INPUT_PULLUP); pinMode(GPIB_DIO6,INPUT_PULLUP); pinMode(GPIB_DIO3,INPUT_PULLUP); pinMode(GPIB_DIO7,INPUT_PULLUP); pinMode(GPIB_DIO4,INPUT_PULLUP); pinMode(GPIB_DIO8,INPUT_PULLUP); pinMode(GPIB_EOI, INPUT_PULLUP); pinMode(GPIB_REN, INPUT_PULLUP); set_num(GPIB_DIO1, 0); set_num(GPIB_DIO5, 0); set_num(GPIB_DIO2, 0); set_num(GPIB_DIO6, 0); set_num(GPIB_DIO3, 0); set_num(GPIB_DIO7, 0); set_num(GPIB_DIO4, 0); set_num(GPIB_DIO8, 0); set_num(GPIB_EOI, 0); set_num(GPIB_REN, 0); pinMode(GPIB_DAV, INPUT_PULLUP); pinMode(GPIB_NRFD,INPUT_PULLUP); pinMode(GPIB_NDAC,INPUT_PULLUP); set_num(GPIB_DAV, 0); set_num(GPIB_NRFD, 1); set_num(GPIB_NDAC, 1); //set_num(GPIB_SRQ, 0); //RST pinMode(GPIB_IFC, INPUT_PULLUP); pinMode(GPIB_ATN, INPUT_PULLUP); set_num(GPIB_IFC, 0); set_num(GPIB_ATN, 0); } byte get_dio() { //negative logic byte x = 0; bitWrite(x, 0, !set_num(GPIB_DIO1,0)); bitWrite(x, 1, !set_num(GPIB_DIO2,0)); bitWrite(x, 2, !set_num(GPIB_DIO3,0)); bitWrite(x, 3, !set_num(GPIB_DIO4,0)); bitWrite(x, 4, !set_num(GPIB_DIO5,0)); bitWrite(x, 5, !set_num(GPIB_DIO6,0)); bitWrite(x, 6, !set_num(GPIB_DIO7,0)); bitWrite(x, 7, !set_num(GPIB_DIO8,0)); return x; } void set_dio(byte x) { //negative logic in set_num set_num(GPIB_DIO1,bitRead(x,0)); set_num(GPIB_DIO2,bitRead(x,1)); set_num(GPIB_DIO3,bitRead(x,2)); set_num(GPIB_DIO4,bitRead(x,3)); set_num(GPIB_DIO5,bitRead(x,4)); set_num(GPIB_DIO6,bitRead(x,5)); set_num(GPIB_DIO7,bitRead(x,6)); set_num(GPIB_DIO8,bitRead(x,7)); } boolean gpibWait(int ch, char hl){ unsigned long count=timeout; count*=1000; // ms to us while(hl == digitalRead(ch) && --count){delayMicroseconds(1);} return count==0; // true if timeout } boolean gpibWrite(byte data) {// return true if error set_num(GPIB_NDAC,0); if(gpibWait(GPIB_NDAC,HIGH)){return true;} //until (LOW == NDAC) set_dio(data); // output data to DIO set_num(GPIB_NRFD,0); if(gpibWait(GPIB_NRFD,LOW)){return true;} //until (HIGH == NRFD) set_num(GPIB_DAV,1); // validate data if(gpibWait(GPIB_NDAC,LOW)){return true;} //until (HIGH == NDAC) set_num(GPIB_DAV,0); set_dio(0); delayMicroseconds(30); return false; } boolean gpibRead(byte *data) {// return true when EOI==LOW or error boolean ret; set_num(GPIB_NRFD,0); // prepare to listen set_num(GPIB_DAV,0); set_num(GPIB_EOI,0); if(gpibWait(GPIB_DAV,HIGH)){return true;} //until (LOW == DAV) set_num(GPIB_NRFD,1); // Ready for data *data = get_dio(); // input data from DIO ret=(LOW == digitalRead(GPIB_EOI)); // check EOI set_num(GPIB_NDAC,0); // data accepted if(gpibWait(GPIB_DAV,LOW)){return true;} //until (HIGH == DAV) set_num(GPIB_NDAC,1); return ret; } void initEndPoint(){ UEP1_DMA = (uint16_t) Ep1outBuffer; // EP1 data transfer address UEP1_CTRL = bUEP_AUTO_TOG // EP1 Auto flip sync flag | UEP_T_RES_NAK // EP1 IN transaction returns NAK | UEP_R_RES_ACK; // EP1 OUT transaction returns ACK UEP4_1_MOD = bUEP1_RX_EN | bUEP1_TX_EN; // EP1 OUT/IN buffer } uint16_t handleVendorControlTransfer(){ //vendor request uint16_t value; value=UsbSetupBuf->wValueH; value=(value<<8) | UsbSetupBuf->wValueL; switch(UsbIntrSetupReq){ //UsbSetupBuf->bRequest case GPIB_EP1: if(value)UEP1_CTRL=(UEP1_CTRL & ~MASK_UEP_R_RES & ~MASK_UEP_T_RES) | (UsbSetupBuf->wValueL & (MASK_UEP_R_RES | MASK_UEP_T_RES) ); *Ep0Buffer=UEP1_CTRL; break; case GPIB_DIO_LINE : if(value){set_dio(*Ep0Buffer=UsbSetupBuf->wValueL);} else{*Ep0Buffer=get_dio();} break; case GPIB_EOI_LINE : *Ep0Buffer=set_num(GPIB_EOI,UsbSetupBuf->wValueL); break; case GPIB_DAV_LINE : *Ep0Buffer=set_num(GPIB_DAV,UsbSetupBuf->wValueL); break; case GPIB_NRFD_LINE : *Ep0Buffer=set_num(GPIB_NRFD,UsbSetupBuf->wValueL); break; case GPIB_NDAC_LINE : *Ep0Buffer=set_num(GPIB_NDAC,UsbSetupBuf->wValueL); break; case GPIB_IFC_LINE : *Ep0Buffer=set_num(GPIB_IFC,UsbSetupBuf->wValueL); break; case GPIB_SRQ_LINE : *Ep0Buffer=readSRQ(); break; case GPIB_ATN_LINE : *Ep0Buffer=set_num(GPIB_ATN,UsbSetupBuf->wValueL); break; case GPIB_REN_LINE : *Ep0Buffer=set_num(GPIB_REN,UsbSetupBuf->wValueL); break; case GPIB_READ : gpibRead(Ep0Buffer); break; case GPIB_WRITING : if(value)writing=UsbSetupBuf->wValueL; *Ep0Buffer=writing; break; case GPIB_READING : if(value)reading=UsbSetupBuf->wValueL; *Ep0Buffer=reading; break; case GPIB_READY : if(value)ready=UsbSetupBuf->wValueL; *Ep0Buffer=ready; break; case GPIB_LNGTH : if(value)lngth=UsbSetupBuf->wValueL; *Ep0Buffer=lngth; break; case GPIB_EOS : if(value)eos=UsbSetupBuf->wValueL; *Ep0Buffer=eos; break; case GPIB_EOT : if(value)eot=UsbSetupBuf->wValueL; *Ep0Buffer=eot; break; case GPIB_TIMEOUT : if(value)timeout=value; Ep0Buffer[0]=timeout & 0xff; Ep0Buffer[1]=timeout>>8; return 2; break; case GPIB_TTLSZ : if(value)ttlsz=value; Ep0Buffer[0]=ttlsz & 0xff; Ep0Buffer[1]=ttlsz>>8; return 2; break; default: return 0xFF; // Command not supported } // end of the switch return 1; // no data to transfer back to the host } void handlerVendorEndPoint1out(){ // host to device lngth=0; if ( U_TOG_OK ) { // Out-of-sync packets will be discarded // UEP1_CTRL ^= bUEP_R_TOG; // Automatically flipped lngth = USB_RX_LEN; UEP1_CTRL = (UEP1_CTRL & ~MASK_UEP_R_RES) | UEP_R_RES_NAK; // respond NAK. Let main code change response after handling. writing=true; // write through GPIB in main code } ready=false; } void handlerVendorEndPoint1in(){ // device to host UEP1_CTRL = (UEP1_CTRL & ~ MASK_UEP_T_RES) | UEP_T_RES_NAK; //NAK by default ready = false; } void setup() { delay(5); init_GPIB(); USBDeviceCfg(); } void loop() { uint8_t pos=0; if(writing && !ready){ // write to instrument for(pos=0;pos