-- Title: USB HID device demo -- Author: Albert Faber, Copyright (c) 2008..2009, all rights reserved. -- Adapted-by: - -- Compiler: >=2.4j --- modified by Jean-Pierre Mandon 2009 for Pinguino compatibility -- -- This file is part of jallib (http://jallib.googlecode.com) -- Released under the BSD license (http://www.opensource.org/licenses/bsd-license.php) -- -- Description: This application emulates a mouse pointing USB human interface device -- (HID), once the USB device has been conifgured and the USB HID is recognized by -- the host operating systems, it will move around the mouse pointer -- -- -- -- Sources: http://www.usb.org for USB specifications -- -- Notes: compiled with following flags -- -loader18 8224 -no-fuse -- use -no-variable-reuse when debugging flags are -- set due to a compiler issue -- -- ------------------------------------------------------ -- ------------------------------------------------------ -- -- -- -- This file has been generated from: -- * board: board_18f4550_af.jal -- * test : test_usb_hid_mouse.jal -- ;@jallib section board_description ;@jallib section chipdef -- chip setup include 18f4550 -- even though the external crystal is 20 MHz, the configuration is such that -- the CPU clock is derived from the 96 Mhz PLL clock (div2), therefore set -- target frequency to 48 MHz pragma target clock 48_000_000 --- add this code to stop Pinguino USB module --- Jean-Pierre Mandon UCON=0 UCFG=0 var byte big_loop = 1 --- word while big_loop != 0 loop big_loop = big_loop + 1 end loop --- end code for compatibility with Pinguino -- fuses pragma target PLLDIV DIVIDE_BY_5_20MHZ_INPUT pragma target CPUDIV OSC1_OSC2_SRC_1_96MHZ_PLL_SRC_2 pragma target USBPLL CLOCK_SRC_FROM_96MHZ_PLL_2 pragma target OSC HS_PLL pragma target FCMEN DISABLED pragma target IESO DISABLED pragma target PWRTE DISABLED -- power up timer pragma target VREGEN ENABLED -- USB voltage regulator pragma target VOLTAGE V20 -- brown out voltage pragma target BROWNOUT DISABLED -- no brownout detection pragma target WDTPS P32768 -- watch dog saler setting pragma target WDT DISABLED -- no watchdog pragma target CCP2MUX pin_C1 -- CCP2 pin pragma target PBADEN DIGITAL -- digital input port<0..4> pragma target LPT1OSC DISABLED -- low power timer 1 pragma target MCLR EXTERNAL -- master reset on RE3 pragma target STVR DISABLED -- reset on stack over/under flow pragma target LVP DISABLED -- no low-voltage programming pragma target XINST ENABLED -- extended instruction set pragma target BACKBUG DISABLED -- background debugging pragma target CP_0 DISABLED -- code block 0 not protected pragma target CP_1 DISABLED -- code block 1 not protected pragma target CP_2 DISABLED -- code block 2 not protected pragma target CP_3 DISABLED -- code block 3 not protected pragma target CPB DISABLED -- bootblock code not write protected pragma target CPD DISABLED -- eeprom code not write protected pragma target WRT_0 DISABLED -- table writeblock 0 not protected pragma target WRT_1 DISABLED -- table write block 1 not protected pragma target WRT_2 DISABLED -- table write block 2 not protected pragma target WRT_3 DISABLED -- table write block 3 not protected pragma target WRTB DISABLED -- bootblock not write protected pragma target WRTD DISABLED -- eeprom not write protected pragma target WRTC DISABLED -- config not write protected pragma target EBTR_0 DISABLED -- table read block 0 not protected pragma target EBTR_1 DISABLED -- table read block 1 not protected pragma target EBTR_2 DISABLED -- table read block 2 not protected pragma target EBTR_3 DISABLED -- table read block 3 not protected pragma target EBTRB DISABLED -- boot block not protected include delay ;@jallib section serial -- whether or not using the serial port const HAS_SERIAL_DEBUG_PORT = 1 if defined( HAS_SERIAL_DEBUG_PORT ) == true then const serial_hw_baudrate = 115_200 include serial_hardware include format include print -- intialze serial device serial_hw_init() -- uncomment when directly coupled (i.e. without max 232) to rs-232C -- BAUDCON_CKTXP = true procedure serial_print_spc() is serial_hw_write( " " ) end procedure procedure serial_newline() is serial_hw_write( 10 ) -- serial_hw_write( 13 ) end procedure end if const bit USB_DEBUG = false const bit USB_DEBUG_HIGH = false const bit USB_HID_DEBUG = false const bit USB_HID_DEBUG_HIGH = false const byte USB_HID_ENDPOINT = 0x01 var volatile bit usb_hid_can_tx = true include usb_defs const bit USB_EP0 = 1 const byte USB_EP0_OUT_SIZE = 8 const word USB_EP0_OUT_ADDR = ( USB_BASE_ADDRESS + 0x0010 ) const byte USB_EP0_IN_SIZE = 8 const word USB_EP0_IN_ADDR = ( USB_EP0_OUT_ADDR + USB_EP0_OUT_SIZE ) const bit USB_EP1 = 1 const byte USB_EP1_OUT_SIZE = 8 const word USB_EP1_OUT_ADDR = ( USB_EP0_IN_ADDR + USB_EP0_IN_SIZE ) const byte USB_EP1_IN_SIZE = 8 const word USB_EP1_IN_ADDR = ( USB_EP1_OUT_ADDR + USB_EP1_OUT_SIZE ) var volatile byte usb_ep1in_buf[ 8 ] at USB_EP1_IN_ADDR const bit USB_EP2 = 0 const byte USB_EP2_OUT_SIZE = 8 const word USB_EP2_OUT_ADDR = 0x0000 const byte USB_EP2_IN_SIZE = 8 const word USB_EP2_IN_ADDR = 0x0000 const bit USB_EP3 = 0 const byte USB_EP3_OUT_SIZE = 8 const word USB_EP3_OUT_ADDR = 0x0000 const byte USB_EP3_IN_SIZE = 8 const word USB_EP3_IN_ADDR = 0x0000 const byte USB_DEVICE_DESCRIPTOR[USB_DEVICE_DESCRIPTOR_SIZE] = { USB_DEVICE_DESCRIPTOR_SIZE, -- 18 bytes long USB_DT_DEVICE, -- DEVICE 01h 0x00, 0x02, -- usb version 2.00 0x00, -- class 0x00, -- subclass 0x00, -- protocol 0x08, -- max packet size for end point 0 0xd8, 0x04, -- Microchip's vendor 0x00, 0x00, -- Mouse circle demo 0x02, 0x00, -- version 2.0 of the product 0x01, -- string 1 for manufacturer 0x02, -- string 2 for product 0x00, -- string 3 for serial number 0x01 -- number of configurations } const USB_CONFIGURATION_DESCRIPTOR_SIZE = 0x09 + 0x09 + 0x09 + 0x07 const byte USB_HID_REPORT1[]= { 0x05, 0x01, -- Usage Page (Generic Desktop) 0x09, 0x02, -- Usage (Mouse) 0xA1, 0x01, -- Collection (Application) 0x09, 0x01, -- Usage (Pointer) 0xA1, 0x00, -- Collection (Physical) 0x05, 0x09, -- Usage Page (Buttons) 0x19, 0x01, -- Usage Minimum (01) 0x29, 0x03, -- Usage Maximum (03) 0x15, 0x00, -- Logical Minimum (0) 0x25, 0x01, -- Logical Maximum (0) 0x95, 0x03, -- Report Count (3) 0x75, 0x01, -- Report Size (1) 0x81, 0x02, -- Input (Data, Variable, Absolute) 0x95, 0x01, -- Report Count (1) 0x75, 0x05, -- Report Size (5) 0x81, 0x01, -- Input (Constant), 5 bit padding 0x05, 0x01, -- Usage Page (Generic Desktop) 0x09, 0x30, -- Usage (X) 0x09, 0x31, -- Usage (Y) 0x15, 0x81, -- Logical Minimum (-127) 0x25, 0x7F, -- Logical Maximum (127) 0x75, 0x08, -- Report Size (8) 0x95, 0x02, -- Report Count (2) 0x81, 0x06, -- Input (Data, Variable, Relative) 0xC0, 0xC0 } const byte USB_CONFIGURATION_DESCRIPTOR[ USB_CONFIGURATION_DESCRIPTOR_SIZE ]= { -- configuration descriptor - - - - - - - - - - 0x09, -- length, USB_DT_CONFIGURATION, -- descriptor_type USB_CONFIGURATION_DESCRIPTOR_SIZE, 0x00, -- total_length; 0x01, -- num_interfaces, 0x01, -- configuration_value, 0x00, -- configuration_string_id, 0b10000000, -- attributes (bus powered, no remote wake up) 100, -- max_power; (200ma) -- interface descriptor - - - - - - - - - - - - 0x09, -- length, USB_DT_INTERFACE, -- descriptor_type, 0x00, -- interface_number, (starts at zero) 0x00, -- alternate_setting, (no alternatives) 0x01, -- num_endpoints, 0x03, -- interface_class, (HID) 0x01, -- interface_subclass, (boot - is this necessary?) 0x02, -- interface_protocol, (mouse) 0x00, -- interface_string_id; -- hid descriptor - - - - - - - - - - - - - - - 0x09, -- length, USB_DT_HID, -- descriptor_type; 0x11, 0x01, -- hid_spec in BCD (1.11) 0x00, -- country_code, (0=not country specific) 0x01, -- num_class_descriptors, (1) USB_DT_HID_REPORT, -- class_descriptor_type; (0x22 = report) (count( USB_HID_REPORT1 ) & 0xFF ), (count( USB_HID_REPORT1 ) >> 8 ), 0x07, -- length, USB_DT_ENDPOINT, -- descriptor_type, 0b10000001, -- endpoint_address, (Endpoint 1, IN) 0b00000011, -- attributes; (Interrupt) 0x03, 0x00, -- max_packet_size 0x0A -- interval (10ms) } const byte USB_STRING0[] = { 0x04, -- bLength USB_DT_STRING, -- bDescriptorType 0x09, -- wLANGID[0] (low byte) 0x04 -- wLANGID[0] (high byte) } const byte USB_STRING1[] = { 0x36, -- bLength USB_DT_STRING, -- bDescriptorType "M", 0x00, "i", 0x00, "c", 0x00, "r", 0x00, "o", 0x00, "c", 0x00, "h", 0x00, "i", 0x00, "p", 0x00, " ", 0x00, "T", 0x00, "e", 0x00, "c", 0x00, "h", 0x00, "n", 0x00, "o", 0x00, "l", 0x00, "o", 0x00, "g", 0x00, "y", 0x00, ",", 0x00, " ", 0x00, "I", 0x00, "n", 0x00, "c", 0x00, ".", 0x00 } const byte USB_STRING2[44] = { 44, -- bLength USB_DT_STRING, -- bDescriptorType "J", 0x00, "A", 0x00, "L", 0x00, "L", 0x00, "I", 0x00, "B", 0x00, " ", 0x00, "H", 0x00, "I", 0x00, "D", 0x00, " ", 0x00, "M", 0x00, "o", 0x00, "u", 0x00, "s", 0x00, "e", 0x00, " ", 0x00, "D", 0x00, "e", 0x00, "m", 0x00, "o", 0x00 } include usb_drv_core procedure usb_ep_data_in_callback(byte in end_point, word in buffer_addr, byte in byte_count) is pragma inline if USB_HID_DEBUG_HIGH then const byte str[] = " EP data in: " const byte str1[] = " bytes " print_string( serial_hw_data,str ) print_byte_hex( serial_hw_data, byte_count & 0xFF) print_string(serial_hw_data,str1) end if -- data has been sent, so do we need to send more? if (end_point == USB_HID_ENDPOINT) then -- it's the data end point usb_hid_can_tx = true end if end procedure include usb_drv -- constants const sbyte dir_table[] = {-4,-4,-4, 0, 4, 4, 4, 0} const byte str_welcome[] = "JALLIB USB HID MOUSE DEMO version 1.0\nplease wait (takes ~10 seconds) before the device it is fully configured" -- variables var word i = 0 var byte movement_length var byte vector = 0 var bit usb_initialized = false var byte data_buffer[3] var word ticks100us = 0 var bit enable_mouse = false procedure usb_tasks() is -- Servicing Hardware -- use polling method usb_handle_isr() end procedure -- interrupts? No thanks while INTCON_GIE loop INTCON_GIE = false end loop if defined( HAS_SERIAL_DEBUG_PORT ) == high then -- put info on RS-232 serial line serial_newline() serial_newline() print_string(serial_hw_data, str_welcome ) serial_newline() end if -- setup the USB device usb_setup() -- enable USB device usb_enable_module() -- initialize HID buffer data_buffer[0] = 0x00 data_buffer[1] = 0x00 data_buffer[2] = 0x00 -- main loop forever loop -- poll the usb ISR function on a regular base, in order to -- serve the USB requests usb_tasks() -- check if USB device has been configured by the HOST if usb_is_configured() then -- note user via serial line that USB has been configured if usb_initialized == false then usb_initialized = true if defined( HAS_SERIAL_DEBUG_PORT ) == true then const byte str[] = "USB device has been configured by the HOST!" print_string(serial_hw_data, str ) serial_newline() end if end if -- now the mouse pointer can be moved around enable_mouse = true end if if enable_mouse then ticks100us = ticks100us + 1 delay_10us(10) if ticks100us == 250 then ticks100us = 0 if( movement_length > 16 ) then data_buffer[0] = 0 data_buffer[1] = byte( dir_table[vector & 0x07] ) -- X-Vector data_buffer[2] = byte( dir_table[(vector+2) & 0x07] ) -- Y-Vector vector = vector+1 movement_length = 0 end if if ( usb_hid_can_tx ) then usb_hid_can_tx = false usb_send_data(1, data_buffer, 3, low ) movement_length = movement_length + 1 end if end if end if if defined( HAS_SERIAL_DEBUG_PORT ) == true then if PIR1_RCIF then serial_hw_write( RCREG ) if RCREG == "S" then end if if RCREG == "T" then end if end if end if end loop