//////////////////////////////////////////////////////////////////////////////// /*! @file Microsin_USB_IO.c USB interface for the Microsin device. - Part of the MSDN firmware. - Part of the Research Assistant project. - Uses LUFA library written by - Copyright(C) 2012, Dean Camera, dean [at] fourwalledcubicle [dot] com, www.lufa-lib.org. - This file is based on the examples provided with LUFA Library. - It has been modified by - Copyright(C) 2014, Dmitry K. Nelson, St.Petersburg, Russia. D.Nelson@mail.ioffe.ru - Copyright(C) 2016, Viktor E. Bursian, St.Petersburg, Russia. Viktor.Bursian@mail.ioffe.ru */////////////////////////////////////////////////////////////////////////////// #include "Microsin_USB_IO.h" #include #include #include //В следующем файле подключается нужный процессор, //исходя из переменных в make-файле *.mk, //но QtCreator об этом не знает и, например, поиск деклараций не работает. #include //Можно прямо указать нужный header: //#include //! @todo{MSDN} Неясная роль inttypes здесь #include //#include /*! LED mask for the library LED driver, to indicate that the USB interface is not ready. */ #define LEDMASK_USB_NOTREADY LEDS_LED1 /*! LED mask for the library LED driver, to indicate that the USB interface is enumerating. */ #define LEDMASK_USB_ENUMERATING (LEDS_LED2 | LEDS_LED3) /*! LED mask for the library LED driver, to indicate that the USB interface is ready. */ #define LEDMASK_USB_READY (LEDS_LED2 | LEDS_LED4) /*! LED mask for the library LED driver, to indicate that an error has occurred in the USB interface. */ #define LEDMASK_USB_ERROR (LEDS_LED1 | LEDS_LED3) /*! LUFA CDC Class driver interface configuration and state information. This structure is passed to all CDC Class driver functions, so that multiple instances of the same class within a device can be differentiated from one another. */ USB_ClassInfo_CDC_Device_t VirtualSerial_CDC_Interface = { .Config = { .ControlInterfaceNumber = 0, .DataINEndpoint = { .Address = CDC_TX_EPADDR, .Size = CDC_TXRX_EPSIZE, .Banks = 1, }, .DataOUTEndpoint = { .Address = CDC_RX_EPADDR, .Size = CDC_TXRX_EPSIZE, .Banks = 1, }, .NotificationEndpoint = { .Address = CDC_NOTIFICATION_EPADDR, .Size = CDC_NOTIFICATION_EPSIZE, .Banks = 1, }, }, }; /*! Circular buffer to hold data before it is sent to the host. */ static RingBuffer_t ToSendtoUSB_Buffer; /*! Underlying data buffer for \ref ToSendtoUSB_Buffer, where the stored bytes are located. */ static uint8_t ToSendtoUSB_Buffer_Data[128]; /*! Event handler for the library USB Connection event. */ void EVENT_USB_Device_Connect (void) { LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING); } /*! Event handler for the library USB Disconnection event. */ void EVENT_USB_Device_Disconnect (void) { LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); } /*! Event handler for the library USB Configuration Changed event. */ void EVENT_USB_Device_ConfigurationChanged (void) { LEDs_SetAllLEDs( CDC_Device_ConfigureEndpoints(&VirtualSerial_CDC_Interface) ? LEDMASK_USB_READY : LEDMASK_USB_ERROR ); } /*! Event handler for the library USB Control Request reception event. */ void EVENT_USB_Device_ControlRequest (void) { CDC_Device_ProcessControlRequest(&VirtualSerial_CDC_Interface); } void MicrosinLEDTurnOn (void) { LEDs_TurnOffLEDs(LEDS_LED1); // ^^^ that's right! A bug in LUFA? } void MicrosinLEDTurnOff (void) { LEDs_TurnOnLEDs(LEDS_LED1); // ^^ that's right! A bug in LUFA? } void Send_EOL_ToUSB (void) { if( USB_DeviceState == DEVICE_STATE_Configured ){ #ifdef CR_LF_ENDINGS RingBuffer_Insert(&ToSendtoUSB_Buffer,0x0D); // Symbol CR #endif RingBuffer_Insert(&ToSendtoUSB_Buffer,0x0A); // Symbol LF } } void SendCharToUSB (char character) { if( USB_DeviceState == DEVICE_STATE_Configured ){ RingBuffer_Insert(&ToSendtoUSB_Buffer,character); } } void SendStringToUSB (const char * const string_of_chars) { if( USB_DeviceState == DEVICE_STATE_Configured ){ for(int8_t i=0 ; string_of_chars[i] ; i++ ){ RingBuffer_Insert(&ToSendtoUSB_Buffer,string_of_chars[i]); }; } } uint8_t LeadingZeroes = 0; void SendNumberToUSB (int32_t number) { const uint32_t Mask = 0x0000000F; uint8_t Digit; uint8_t DoSendZeroes = LeadingZeroes; if( USB_DeviceState == DEVICE_STATE_Configured ){ for( int8_t i=28 ; i>=0 ; i-=4 ){ Digit = ( number & ( Mask << i) ) >> i; if( Digit < 0xA ){ if( Digit || DoSendZeroes || ! i ){ DoSendZeroes = 1; RingBuffer_Insert(&ToSendtoUSB_Buffer,Digit+0x30); } }else{ DoSendZeroes = 1; RingBuffer_Insert(&ToSendtoUSB_Buffer,Digit+0x37);//+0x41-0xA } } } } int8_t SendByByte = 0; int8_t USBByClock = 0; int8_t USBClockSignal = 1; /*! Main program initialises everything and performs the main program loop. */ int main(void) { SetupHardware(); LEDs_Init(); USB_Init(); RingBuffer_InitBuffer(&ToSendtoUSB_Buffer ,ToSendtoUSB_Buffer_Data ,sizeof(ToSendtoUSB_Buffer_Data)); LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); sei(); BeforeLoop(); for(;;){ if( ! USBByClock || USBClockSignal ){ USBClockSignal = 0; if( CDC_Device_BytesReceived(&VirtualSerial_CDC_Interface) ){ // There is somewhat to read ProcessReceivedByte(CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface)); } /* Check if the buffer is not empty */ uint16_t BufferCount = RingBuffer_GetCount(&ToSendtoUSB_Buffer); if( BufferCount && SendByByte ) BufferCount = 1; while( BufferCount-- ){ /* Try to send the next byte of data to the host */ if( CDC_Device_SendByte(&VirtualSerial_CDC_Interface ,RingBuffer_Peek(&ToSendtoUSB_Buffer) ) != ENDPOINT_READYWAIT_NoError ){ break; //abort if there is an error without dequeuing } /* Dequeue the already sent byte from the buffer */ RingBuffer_Remove(&ToSendtoUSB_Buffer); } /*! @todo{MSDN} Что делают CDC_Device_USBTask и USB_USBTask? Тут ли им место? */ CDC_Device_USBTask(&VirtualSerial_CDC_Interface); USB_USBTask(); } InLoop(); } }