Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.



RC5-USB-клава отрубается.

Сообщений 1 страница 16 из 16

1

Пытаюсь сделать пульт для медиацентра имитирующий USB клавиатуру.

Всё работает но проходит 5 минут и компьютер теряет интерес к моему устройству, хотя оно не виснет.

Проверял на 3х компах.

USBlizer показывает начало какого-то обмена со стороны компа и как будь-то не получив ответа херит это дело совсем.
Хотя обычная USB клава может бездействовать бесконечно долго и никто её ни о чем не спрашивает.

Три дня прошло, а воз и ныне там.

0

2

Основа
исходник

Код:
'*******************************************************************************
'----------------------- Мультимедиа-Клавиатура HID на USB ---------------------
'*******************************************************************************
'
'                                Bascom -avr V.2.0.4.0
'                                  Rubashka Vasiliy
'                                      Ukraine
'                                       2011
'                             Combined by MrShilov © 2012
'
'$prog &HFF , &HFF , &HD9 , &HFF                             'Take care that the chip supports all fuse bytes.


$noramclear
$hwstack = 40
$swstack = 40
$framesize = 50
$regfile = "m8def.dat"                                      'ATMEGA8-16PU
$crystal = 12000000                                         'Кварц - был 15МГц, заменен на 12МГц !!!!!!!!!!!!!!!!

'Include the software USB library - NEW
$lib "swusb.lbx"
$external _swusb

Declare Sub Usb_reset()
Declare Sub Usb_processsetup(txstate As Byte)
Declare Sub Usb_send(txstate As Byte , Byval Count As Byte)
Declare Sub Usb_senddescriptor(txstate As Byte , Maxlen As Byte)

'*************************** Конфигурация USB **********************************
'
'Set the following parameters to match your hardware configuration and USB
'device parameters.

'******************************* USB Connections *******************************

'Define the AVR port that the two USB pins are connected to
_usb_port Alias Portd
_usb_pin Alias Pind
_usb_ddr Alias Ddrd



'Define the D+ and D- pins. (put D+ on an interrupt pin)
Const _usb_dplus = 2
Const _usb_dminus = 4


'          +--*--------------*---------*--------------------+
'       0,1|  |              |         |    ATMEGA 8        |
'         --- |        +-----+---[1k5]-+    +--\/--+        |
'   USB   --- |        |     +---[10k]---*--|1   28|        |
'          |  |   CAPS | +--|<|--[300]---+--|2   27|        |
'  /---\   |  |   NUM  | *--|<|--[300]---+--|3   26|        |
' | VCC|-1-+--+ +------+-+-------[68 ]---+--|4   25|        |
'  \   |   |    | LOCK | *--|<|--[300]---+--|5   24|        |
'   |D-|-2-+--*-+------*-+-------[68 ]---+--|6   23|        |
'   |  |   |  | |        |            +--+--|7   22|--------+-+
'   |D+|-3-+--+-*-L<|----*------------+--+--|8   21|        | |
'  /   |   |  |          | +----------+--+--|9   20|--------* |
' | GND|-4-*  +---L<|----* |  ===  +--+--+--|10  19|------+ | |
'  \---/   |    2x3,6v   | +-12MHz-+  |  |  |11  18|----+ | | |
'          |             |    ===     |  |  |12  17|--+ | | | |
'          +-------------*--|<|--[300]+--+--|13  16|  | | | | |
'                        |STATUS      |  |  |14  15|  | | | | |
'                        |            |  |  +------+  | | | | |
'                        |            |  +----------+ | | | | |
'                        |            *-------*-----+-+-+-+-* |
'                        |            |0,1   +|22,0 | | | | | |
'                        |           ---     ---    | | | | | |
'                        |           ---     ---    | | | | | |
'                        |            |       |     | | | | | |
'                        *------------*-------*-----+-+-+-+-+-*
'                        |                          | | | | | |
'                       ===                         V V V V V V
'
'                                                   R M M S V G
'                                                   E O I C C N
'                                                   S S S K C D

'Configure the pins as inputs

Ddrb = &B11110011                                           'направление линий порта B: 1 - на вывод
Portb = &B00011111                                          'исходное состояние линий B: 00000000
Ddrc = &B00000000                                           'направление линий порта C: 1 - на вывод
Portc = &B11111111                                          'исходное состояние линий C: 00000000
Ddrd = &B11101011                                           'направление линий порта D: 1 - на вывод
Portd = &B00000000                                          'исходное состояние линий D: 00000000


Config Pinb.0 = Input                                       ' энкодер
Config Pinb.1 = Input
Portb = 255
Config Rc5 = Pind.3
Config Pind.3 = Input
Config Portc.1 = Output
Config Portd.1 = Output
Portd.1 = 1                                                 '
'disable pullups
_usb_port._usb_dplus = 0
_usb_port._usb_dminus = 0

'************************* USB константы конфигурации **************************

'Использовать EEPROM или FLASH для хранения USB дескрипторов
'1 = EEPROM, 0 = FLASH.  Использование EEPROM немного уменьшит размер кода.
Const _usb_use_eeprom = 0

'Don't wait for sent packets to be ACK'd by the host before marking the
'transmission as complete.  This option breaks the USB spec but improves
'throughput with faster polling speeds.
'This may cause reliability issues.  Should leave set to 0 to be safe.
Const _usb_assume_ack = 0

'***************************** Дескриптор устройства****************************

'USB Vendor ID and Product ID (Assigned by USB-IF)
Const _usb_vid = &HBBBB
Const _usb_pid = &HEF33

'USB Device Release Number (BCD)
Const _usb_devrel = &H0001

'USB Release Spec (BCD)
Const _usb_spec = &H0110

'USB Device Class, subclass, and protocol (assigned by USB-IF).
'&h00 = Class defined by interface. (HID is defined in the interface)
'&hFF = Vendor-defined class (You must write your own PC driver)
'See http://www.usb.org/developers/defined_class  for more information
Const _usb_devclass = 0
Const _usb_devsubclass = 0
Const _usb_devprot = 0

'These are _indexes_ to UNICODE string descriptors for the manufacturer,
'product name, and serial number.  0 means there is no descriptor.
Const _usb_imanufacturer = 1
Const _usb_iproduct = 2
Const _usb_iserial = 0

'Количество конфигураций для этого устройства.  Не изменяйте это если,
'вы не знаете то, что Вы делаете!  Обычно равно 1
Const _usb_numconfigs = 1

'***************************** Конфигурация дискиптора *************************

'Количество интерфейсов для этого устройства (Обычно 1)
'Const _usb_numifaces = 1
Const _usb_numifaces = 2                                    'Теперь у нас 2 интерфейса !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

'Номер конфигурации (не редактировать!)
Const _usb_confignum = 1

'Индекс дескриптора строки УНИКОДА, который описывает эту конфигурацию (0 - отсутствует)
'Const _usb_iconfig = 2
Const _usb_iconfig = 0                                      'Не требуется !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

'&H80 = Устройство питается от шины USB.
'&HC0 = Устройство имеет свой источник питания.
'Const _usb_powered = &H80
Const _usb_powered = &HA0                                   'Питание от шины USB с возможностью "будить" компьютер !!!!!!!!!

'Потребляемый устройством ток * 2mA  (500mA max)
Const _usb_maxpower = 150                                   '50 * 2mA = 100mA

'**************************** Дескрипторы интерфейса ***************************

'Число интерфейсов для этого устройства (1 или 2)
'Const _usb_ifaces = 1
Const _usb_ifaces = 2                                       'Теперь у нас 2 интерфейса !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

'Номер интерфейса
Const _usb_ifaceaddr = 0
Const _usb_ifaceaddr1 = 1                                   'Индекс адреса второго интерфейса ******************************

'Альтернативный индекс
Const _usb_alternate = 0
Const _usb_alternate1 = 0                                   'У второго интерфейса тот же альтернативный адрес **************

'Количество конечных точек для этого интерфейса (исключая  нулевую)
'Const _usb_ifaceendpoints = 2
Const _usb_ifaceendpoints = 1                               'Одна точка для первого интерфейса !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Const _usb_ifaceendpoints1 = 1                              'Одна точка для второго интерфейса *****************************

'USB класс интерфейса, подкласс, и протокол (назначенное USB-IF).
'&h00 = RESERVED
'&hFF = Vendor-defined class (You must write your own PC driver)
'       Other values are USB interface device class. (such as HID)
'See http://www.usb.org/developers/defined_class  for more information
Const _usb_ifclass = 3
Const _usb_ifclass1 = 3                                     'Второй интерфейс тоже по прерыванию ***************************

'Const _usb_ifsubclass = 0
Const _usb_ifsubclass = 1                                   'Для клавиатуры субкласс 1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Const _usb_ifsubclass1 = 0                                  'Для мультимедиа субкласс 0 ************************************

'Const _usb_ifprotocol = 0
Const _usb_ifprotocol = 1                                   'Для клавиатуры протокол 1
Const _usb_ifprotocol1 = 0                                  'Для мультимедиа протокол 0

'Индекс в дескрипторе строки УНИКОДА для этого интерфейса (0 - отсутствует)
Const _usb_iiface = 0
Const _usb_iiface1 = 0                                      'Для мультимедиа тоже отсутствует ******************************
'*************************** Дополнительный HID дескриптор *********************
'HID класс, устройств являются вещами подобно клавиатуре, мыши, джойстику.
'See http://www.usb.org/developers/hidpage/  for the specification,
'tools, and resources.

'Учтите, что для устройства HID, класс устройства, подкласс, и протокол
'должен быть 0. Класс интерфейса должен быть 3 (HID).
'Подкласс Интерфейса и протокола должны быть 0 если Вы не делаете
'клавиатурой или мышь, которые поддерживают встроенный протокол.
'Смотрите страницы 8 и 9 спецификации HID 1.11 PDF.

'Число HID дескриптора  (EXCLUDING report and physical)
'Если Вы не делаете устройство HID, тогда установите эту константу на 0
'Const _usb_hids = 1
Const _usb_hids = 2                                         'Общее количество HID теперь 2 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

'BCD HID releasenumber.  Current spec is 1.11
Const _usb_hid_release = &H0111

'Country code from page 23 of the HID 1.11 specifications.
'Usually the country code is 0 unless you are making a keyboard.
Const _usb_hid_country = 0

' Номер сообщения и физических дескрипторов для этого HID
' Должно быть в 1! Все HID устройства иметь по крайней мере 1 дескриптор сообщения.
Const _usb_hid_numdescriptors = 1

'Use a software tool to create the report descriptor and $INCLUDE it.


'*************************** Дескриптор конечной точки *************************

'Конечная точка 0 не включается здесь.  Эти - только для других
'конечных точек.
'Примечание: HID устройства требуют 1 прерывание В конечной точке

'Адрес дополнительных конечных точек (Должно быть > 0. сделать  комментарием, если не требуется)
Const _usb_endp2addr = 1
Const _usb_endp3addr = 2

'Правильные типы - 0 для управления или 3 для прерывания
Const _usb_endp2type = 3
Const _usb_endp3type = 3

'Направление: 0=Out (от компа), 1=In (в комп). Проигнорированно управляющими конечными точками
Const _usb_endp2direction = 1
'Const _usb_endp3direction = 0
Const _usb_endp3direction = 1                               'Теперь и вторая точка тоже из МК в ПК !!!!!!!!!!!!!!!!!!!!!!!!

' Интервал опроса (мс) для конечных точек прерывания.
' Проигнорированно управляющими конечными точками
' (Должно быть не менее 10)
Const _usb_endp2interval = 10
Const _usb_endp3interval = 10

'*******************************************************************************
'The includes need to go right here--between the configuration constants above
'and the start of the program below.  The includes will automatically calculate
'constants based on the above configuration, dimension required variables, and
'allocate transmit and receive buffers.  Nothing inside the includes file needs
'to be modified.
$include "Const_swusb-includes.bas"
'*******************************************************************************

'**************************** USB Interrupt And Init ***************************
'Инициализация всех переменных, флагов, и бит синхронизации
Call Usb_reset()
Const _usb_intf = Intf0
Config Int0 = Rising
On Int0 Usb_isr Nosave
Enable Int0

Enable Interrupts                                           'Разрешить все прерывания

'*************************** Завершение концигурации USB ***********************
'*******************************************************************************
Led Alias Portc.1
Dim Resetcounter As Word
Dim Idlemode As Byte
Dim Flaginputmsg As Byte                                    'Флаг срабатывания таймера
Dim Keymsg(8) As Byte                                       'Передаваемый репорт (8 байт)
Dim Key(35) As Byte                                         'Массив состояния клавиш
Dim Lastkey(35) As Byte                                     'Массив предыдущего состояния клавиш
Dim K As Byte                                               'Счётчик цикла сканирования клавиш
Dim Paus As Byte                                            'Пауза между передаваемыми символами
Dim B1 As Byte
Dim Address As Byte , Command As Byte
Paus = 50
'Portc = 1
'Portb.5 = 1

'Настроим таймер
Config Timer1 = Timer , Prescale = 256
On Timer1 Setflag
Enable Timer1

'Помигаем светодиодом статуса - контроллер стартовал
Led = 1
Waitms 100
Led = 0
Waitms 300
Led = 1
Waitms 100
Led = 0
Waitms 300
Led = 1
Waitms 100
Led = 0

' Формат передаваемого репорта  - usb_tx_buffer:

   _usb_tx_buffer2(2) = 0                                   ' modifier    - комбинация из 8-ми модификаций (левые и правые Ctrl, Alt, Shift, Win)
   _usb_tx_buffer2(3) = 0                                   ' reserved    - резерв
   _usb_tx_buffer2(4) = 0                                   ' keycode 0 - код клавиши 0
   _usb_tx_buffer2(5) = 0                                   ' keycode 1 - код клавиши 1
   _usb_tx_buffer2(6) = 0                                   ' keycode 2 - код клавиши 2
   _usb_tx_buffer2(7) = 0                                   ' keycode 3 - код клавиши 3
   _usb_tx_buffer2(8) = 0                                   ' keycode 4 - код клавиши 4
   _usb_tx_buffer2(9) = 0                                   ' keycode 5 - код клавиши 5

' modifier
' bit0  LEFT CTRL   (1)
' bit1  LEFT SHIFT  (2)
' bit2  LEFT ALT    (4)
' bit3  LEFT WIN    (8)
' bit4  RIGHT CTRL  (16)
' bit5  RIGHT SHIFT (32)
' bit6  RIGHT ALT   (64)
' bit7  RIGHT WIN   (128)

' CTRL + ALT + DEL
' Эту комбинацию нужно передать так: &H05, &H00, &H4С, &H00, &H00, &H00, &H00, &H00 = 5[Ctrl(1) + Alt(4)], 0, 76, 0, 0, 0, 0, 0
' В первый байт попадает сумма модификаций клавиш (левые и правые Ctrl, Alt, Shift, Win)

'******************************* Основной цикл *********************************
Do

   Resetcounter = 0

   'Флаг сброса
   While _usb_pin._usb_dminus = 0
      Incr Resetcounter
      If Resetcounter = 1000 Then
         Call Usb_reset()
      End If
   Wend

   'Флаг полученных данных
   If _usb_status._usb_rxc = 1 Then

      If _usb_status._usb_setup = 1 Then
         'Обработка пакет/управление сообщения установки
         Call Usb_processsetup(_usb_tx_status)
             'Состояние конечных точек изменилось, поэтому управление светодиодами ******************************************
             'перенесем в подпрограмму обработки запросов "Usb_processsetup"       ******************************************

             'Elseif _usb_status._usb_endp1 = 1 Then                ' Пришёл пакет данных с компа     !!!!!!!!!!!!!!!!!!!!!!!
             'Portd.0 = _usb_rx_buffer(2).0                  'Состояние светодиодного индикатора CAPS !!!!!!!!!!!!!!!!!!!!!!!
             'Portd.1 = _usb_rx_buffer(2).1                  'Состояние светодиодного индикатора NUM  !!!!!!!!!!!!!!!!!!!!!!!
             'Portd.3 = _usb_rx_buffer(2).2                  'Состояние светодиодного индикатора LOCK !!!!!!!!!!!!!!!!!!!!!!!
      End If

      'Восстановление бита RXC и установка бита RTR (готовность получить новый пакет)
      _usb_status._usb_rtr = 1
      _usb_status._usb_rxc = 0
   End If

  Getrc5(address , Command)
   If Address = 0 Then
    Command = Command And &B01111111                        'clear the toggle bit toggle bit is bit 7. Extended RC5 bit is in bit 6
   End If



 If Flaginputmsg = 1 Then
 B1 = Encoder(pinb.2 , Pinb.1 , Links , Rechts , 0)        ' опрос энкодера
'*************************** СКАНИРУЕМ КЛАВИАТУРУ ******************************
 Key(1) = Pinc.2
 Key(2) = Pinc.3
 Key(3) = Pinc.4
 Key(4) = Pinc.5
 End If

'************************ команды RC5 ****************************
If Command = 38 Then                                        ' restart USB
 Led = 1
  Ddrd.1 = 0
  Portd.1 = 0
   Waitms 1000
      Waitms 1000
         Waitms 1000
  Ddrd.1 = 1
  Portd.1 = 1
 Led = 0
End If

If Command = 15 Then                                        ' Esc
Led = 1
     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer2(2) = 0                          '
            _usb_tx_buffer2(4) = 29
           Call Usb_send(_usb_tx_status2 , 8)               ' Сообщение в компьютер
           Waitms Paus
     End If
     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer2(2) = 0                          ' Отжатие клавиш
            _usb_tx_buffer2(4) = 0
           Call Usb_send(_usb_tx_status2 , 8)               ' Сообщение в компьютер
           Waitms Paus
     End If
Led = 0
End If

If Command = 63 Then
Led = 1
     If _usb_tx_status._usb_txc = 1 Then                    ' Volume-
             _usb_tx_buffer3(2) = 1                         ' Нажатие клавиш
             _usb_tx_buffer3(3) = 234
             _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
           Waitms Paus
     End If
     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer3(2) = 1                          ' Отжатие клавиш
            _usb_tx_buffer3(3) = 0
            _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
           Waitms Paus
     End If
Led = 0
   End If

If Command = 56 Then
Led = 1
     If _usb_tx_status._usb_txc = 1 Then                    ' Volume+
             _usb_tx_buffer3(2) = 1                         ' Нажатие клавиш
             _usb_tx_buffer3(3) = 233
             _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
           Waitms Paus
     End If
     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer3(2) = 1                          ' Отжатие клавиш
            _usb_tx_buffer3(3) = 0
            _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
           Waitms Paus
     End If
Led = 0
   End If

If Command = 55 Then
Led = 1

     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer2(2) = 0                          ' Пробел
            _usb_tx_buffer2(4) = 44
           Call Usb_send(_usb_tx_status2 , 8)               ' Сообщение в компьютер
           Waitms Paus
     End If
     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer2(2) = 0                          ' Отжатие клавиш
            _usb_tx_buffer2(4) = 0
           Call Usb_send(_usb_tx_status2 , 8)               ' Сообщение в компьютер
           Waitms Paus
     End If

Led = 0
End If

If Command = 17 Then
Led = 1

     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer2(2) = 0                          ' влево
            _usb_tx_buffer2(4) = 80
           Call Usb_send(_usb_tx_status2 , 8)               ' Сообщение в компьютер
           Waitms Paus
     End If
     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer2(2) = 0                          ' Отжатие клавиш
            _usb_tx_buffer2(4) = 0
           Call Usb_send(_usb_tx_status2 , 8)               ' Сообщение в компьютер
           Waitms Paus
     End If

Led = 0
End If
If Command = 16 Then
Led = 1

     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer2(2) = 0                          ' вправо
            _usb_tx_buffer2(4) = 79
           Call Usb_send(_usb_tx_status2 , 8)               ' Сообщение в компьютер
           Waitms Paus
     End If
     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer2(2) = 0                          ' Отжатие клавиш
            _usb_tx_buffer2(4) = 0
           Call Usb_send(_usb_tx_status2 , 8)               ' Сообщение в компьютер
           Waitms Paus
     End If

Led = 0
End If

If Command = 32 Then
Led = 1

     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer2(2) = 0                          ' вверх
            _usb_tx_buffer2(4) = 82
           Call Usb_send(_usb_tx_status2 , 8)               ' Сообщение в компьютер
           Waitms Paus
     End If
     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer2(2) = 0                          ' Отжатие клавиш
            _usb_tx_buffer2(4) = 0
           Call Usb_send(_usb_tx_status2 , 8)               ' Сообщение в компьютер
           Waitms Paus
     End If

Led = 0
End If

If Command = 33 Then
Led = 1

     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer2(2) = 0                          ' вниз
            _usb_tx_buffer2(4) = 81
           Call Usb_send(_usb_tx_status2 , 8)               ' Сообщение в компьютер
           Waitms Paus
     End If
     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer2(2) = 0                          ' Отжатие клавиш
            _usb_tx_buffer2(4) = 0
           Call Usb_send(_usb_tx_status2 , 8)               ' Сообщение в компьютер
           Waitms Paus
     End If

Led = 0
End If

If Command = 59 Then
Led = 1

     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer2(2) = 0                          ' Энтер
            _usb_tx_buffer2(4) = 40
           Call Usb_send(_usb_tx_status2 , 8)               ' Сообщение в компьютер
           Waitms Paus
     End If
     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer2(2) = 0                          ' Отжатие клавиш
            _usb_tx_buffer2(4) = 0
           Call Usb_send(_usb_tx_status2 , 8)               ' Сообщение в компьютер
           Waitms Paus
     End If

Led = 0
End If

If Command = 50 Then
Led = 1
     If _usb_tx_status._usb_txc = 1 Then                    ' Stop
             _usb_tx_buffer3(2) = 1                         ' Нажатие клавиш
             _usb_tx_buffer3(3) = 183
             _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
           Waitms Paus
     End If
     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer3(2) = 1                          ' Отжатие клавиш
            _usb_tx_buffer3(3) = 0
            _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
           Waitms Paus
     End If
Led = 0
   End If

If Command = 43 Then
Led = 1
     If _usb_tx_status._usb_txc = 1 Then                    ' Play/Pause
             _usb_tx_buffer3(2) = 1                         ' Нажатие клавиш
             _usb_tx_buffer3(3) = 205
             _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
           Waitms Paus
     End If
     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer3(2) = 1                          ' Отжатие клавиш
            _usb_tx_buffer3(3) = 0
            _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
           Waitms Paus
     End If
Led = 0
   End If

If Command = 13 Then
Led = 1
     If _usb_tx_status._usb_txc = 1 Then                    ' Mute
             _usb_tx_buffer3(2) = 1                         ' Нажатие клавиш
             _usb_tx_buffer3(3) = 226
             _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
           Waitms Paus
     End If
     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer3(2) = 1                          ' Отжатие клавиш
            _usb_tx_buffer3(3) = 0
            _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
           Waitms Paus
     End If
Led = 0
   End If
If Command = 41 Then
Led = 1
     If _usb_tx_status._usb_txc = 1 Then                    ' Next
             _usb_tx_buffer3(2) = 1                         ' Нажатие клавиш
             _usb_tx_buffer3(3) = 181
             _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
           Waitms Paus
     End If
     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer3(2) = 1                          ' Отжатие клавиш
            _usb_tx_buffer3(3) = 0
            _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
           Waitms Paus
     End If
Led = 0
   End If
   If Command = 44 Then
Led = 1
     If _usb_tx_status._usb_txc = 1 Then                    ' Prew
             _usb_tx_buffer3(2) = 1                         ' Нажатие клавиш
             _usb_tx_buffer3(3) = 182
             _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
           Waitms Paus
     End If
     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer3(2) = 1                          ' Отжатие клавиш
            _usb_tx_buffer3(3) = 0
            _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
           Waitms Paus
     End If
Led = 0
   End If


'*************** команды с клавиатуры ****************
If Key(2) = 0 Then
Led = 1
     If _usb_tx_status._usb_txc = 1 Then                    ' Volume-
             _usb_tx_buffer3(2) = 1                         ' Нажатие клавиш
             _usb_tx_buffer3(3) = 234
             _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
           Waitms Paus
     End If
     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer3(2) = 1                          ' Отжатие клавиш
            _usb_tx_buffer3(3) = 0
            _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
           Waitms Paus
     End If
Led = 0
   End If

If Key(3) = 0 Then
Led = 1
     If _usb_tx_status._usb_txc = 1 Then                    ' Volume+
             _usb_tx_buffer3(2) = 1                         ' Нажатие клавиш
             _usb_tx_buffer3(3) = 233
             _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
           Waitms Paus
     End If
     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer3(2) = 1                          ' Отжатие клавиш
            _usb_tx_buffer3(3) = 0
            _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
           Waitms Paus
     End If
Led = 0
   End If



Loop
'*************************** Конец основного цикла *****************************
'**************************** Энкодер ************************
Links:                                                      ' энкодер в лево
Led = 1
     If _usb_tx_status._usb_txc = 1 Then                    ' Volume-
             _usb_tx_buffer3(2) = 1                         ' Нажатие клавиш
             _usb_tx_buffer3(3) = 234
             _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
           Waitms 30
     End If
     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer3(2) = 1                          ' Отжатие клавиш
            _usb_tx_buffer3(3) = 0
            _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
           Waitms 30
     End If
Led = 0
Return

Rechts:                                                     ' энкодер в право
Led = 1
     If _usb_tx_status._usb_txc = 1 Then                    ' Volume+
             _usb_tx_buffer3(2) = 1                         ' Нажатие клавиш
             _usb_tx_buffer3(3) = 233
             _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
          Waitms 30
     End If
     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer3(2) = 1                          ' Отжатие клавиш
            _usb_tx_buffer3(3) = 0
            _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
          Waitms 30
     End If
Led = 0
Return
'************************ Посылка кода одной клавиши ***************************
'Send_u8:
'
'  If Flaginputmsg = 0 Then
'         If _usb_tx_status._usb_txc = 1 Then
'         Led = 1
'            _usb_tx_buffer2(4) = Keymsg(3)
'           Call Usb_send(_usb_tx_status2 , 8)               ' Сообщение в компьютер
'         Led = 0
'         End If
'   End If
'Return


End

'*******************************************************************************
'**************** Дескрипторы, сохранённые в EEPROM или FLASH ******************
'                     Не изменять порядок дескрипторов!
'
#if _usb_use_eeprom = 1
   $eeprom
#else
   $data
#endif

'Дескрипторы устройства
_usb_devicedescriptor:
Data 18 , 18 , _usb_desc_device , _usb_specl , _usb_spech , _usb_devclass
Data _usb_devsubclass , _usb_devprot , 8 , _usb_vidl , _usb_vidh , _usb_pidl
Data _usb_pidh , _usb_devrell , _usb_devrelh , _usb_imanufacturer
Data _usb_iproduct , _usb_iserial , _usb_numconfigs


'Retrieving the configuration descriptor also gets all the interface and
'endpoint descriptors for that configuration.  It is not possible to retrieve
'only an interface or only an endpoint descriptor.  Consequently, this is a
'large transaction of variable size.

_usb_configdescriptor:
Data _usb_descr_total , 9 , _usb_desc_config , _usb_descr_totall
Data _usb_descr_totalh , _usb_numifaces , _usb_confignum , _usb_iconfig
Data _usb_powered , _usb_maxpower

'_usb_IFaceDescriptor
Data 9 , _usb_desc_iface , _usb_ifaceaddr , _usb_alternate
Data _usb_ifaceendpoints , _usb_ifclass , _usb_ifsubclass , _usb_ifprotocol
Data _usb_iiface

'#if _usb_hids > 0
'_usb_HIDDescriptor
Data _usb_hid_descr_len , _usb_desc_hid , _usb_hid_releasel , _usb_hid_releaseh
Data _usb_hid_country , _usb_hid_numdescriptors

'Next follows a list of bType and wLength bytes/words for each report and
'physical descriptor.  There must be at least 1 report descriptor.  In practice,
'There are usually 0 physical descriptors and only 1 report descriptor.

Data _usb_desc_report
Data 63 , 0                                                 ' первое число должно быть таким же, как количество данных дескриптора HID - _usb_hid_reportdescriptor
'End of report/physical descriptor list
'#endif

'#if _usb_endpoints > 1
'_usb_EndpointDescriptor
Data 7 , _usb_desc_endpoint , _usb_endp2attr , _usb_endp2type , 8 , 0
Data _usb_endp2interval
'#endif

'_usb_IFaceDescriptor1 *************************************************************************************
Data 9 , _usb_desc_iface , _usb_ifaceaddr1 , _usb_alternate1       '                            ***********
Data _usb_ifaceendpoints1 , _usb_ifclass1 , _usb_ifsubclass1 , _usb_ifprotocol1       '         ***********
Data _usb_iiface1                                           '                                   ***********

'_usb_HIDDescriptor1  *************************************************************************************
Data _usb_hid_descr_len , _usb_desc_hid , _usb_hid_releasel , _usb_hid_releaseh       '         ***********
Data _usb_hid_country , _usb_hid_numdescriptors , _usb_desc_report       '                      ***********
Data 50 , 0                                                 'Длина мультимедиа-репорта 50 байт  ***********

'#if _usb_endpoints > 2
'_usb_EndpointDescriptor
'Data 7 , _usb_desc_endpoint , _usb_endp3attr , _usb_endp3type , 8 , 0
Data 7 , _usb_desc_endpoint , _usb_endp3attr , _usb_endp3type , 3 , 0       'Для мультимедиа длина сообщения 3 байта !!!!!!!!!!!!!!!!
Data _usb_endp3interval
'#endif

'#if _usb_hids > 0
_usb_hid_reportdescriptor:
Data 63                                                     'Количество данных дескриптора HID, установить такое же в _usb_desc_report
Data &H05 , &H01                                            '   USAGE_PAGE (Generic Desktop)
Data &H09 , &H06                                            '   USAGE (Keyboard)
Data &HA1 , &H01                                            '   COLLECTION (Application)
Data &H05 , &H07                                            '   USAGE_PAGE (Keyboard)
Data &H19 , &HE0                                            '   USAGE_MINIMUM (Keyboard LeftControl)
Data &H29 , &HE7                                            '   USAGE_MAXIMUM (Keyboard Right GUI)
Data &H15 , &H00                                            '   LOGICAL_MINIMUM (0)
Data &H25 , &H01                                            '   LOGICAL_MAXIMUM (1)
Data &H75 , &H01                                            '   REPORT_SIZE (1)
Data &H95 , &H08                                            '   REPORT_COUNT (8)
Data &H81 , &H02                                            '   INPUT (Data,Var,Abs) ** Modifier Byte **
Data &H95 , &H01                                            '   REPORT_COUNT (1)
Data &H75 , &H08                                            '   REPORT_SIZE (8)
Data &H81 , &H03                                            '   INPUT (Cnst,Var,Abs) ** Reserved Byte **
Data &H95 , &H05                                            '   REPORT_COUNT (5)
Data &H75 , &H01                                            '   REPORT_SIZE (1)
Data &H05 , &H08                                            '   USAGE_PAGE (LEDs)
Data &H19 , &H01                                            '   USAGE_MINIMUM (Num Lock)
Data &H29 , &H05                                            '   USAGE_MAXIMUM (Kana)
Data &H91 , &H02                                            '   OUTPUT (Data,Var,Abs) ** LED Report **
Data &H95 , &H01                                            '   REPORT_COUNT (1)
Data &H75 , &H03                                            '   REPORT_SIZE (3)
Data &H91 , &H03                                            '   OUTPUT (Cnst,Var,Abs) ** LED Report Padding **
Data &H95 , &H06                                            '   REPORT_COUNT (6) ** here we define the maximum number of simultaneous keystrokes we can detect **
Data &H75 , &H08                                            '   REPORT_SIZE (8)
Data &H15 , &H00                                            '   LOGICAL_MINIMUM (0)
Data &H25 , &H65                                            '   LOGICAL_MAXIMUM (101)
Data &H05 , &H07                                            '   USAGE_PAGE (Keyboard)
Data &H19 , &H00                                            '   USAGE_MINIMUM (Reserved (no event indicated))
Data &H29 , &H65                                            '   USAGE_MAXIMUM (Keyboard Application)
Data &H81 , &H00                                            '   INPUT (Data,Ary,Abs) ** Key arrays (6 bytes) **
Data &HC0                                                   '   END_COLLECTION

_usb_hid_reportdescriptor1:                                 '                                               ************
Data 50                                                     '                                               ************
Data &H05 , &H0C                                            'Usage Page (Consumer Devices)                  ************
Data &H09 , &H01                                            'Usage (Consumer Control) * Мультимедиа клавиши ************
Data &HA1 , &H01                                            'Collection (Application)                       ************
Data &H85 , &H01                                            '  Report ID (1)                                ************
Data &H19 , &H00                                            '  Usage Minimum (Undefined)                    ************
Data &H2A , &H3C , &H02                                     '  Usage Maximum (reserved 0x023c)              ************
Data &H15 , &H00                                            '  Logical Minimum (0)                          ************
Data &H26 , &H3C , &H02                                     '  Logical Maximum (572)                        ************
Data &H95 , &H01                                            '  Report Count (1)                             ************
Data &H75 , &H10                                            '  Report Size (16)                             ************
Data &H81 , &H00                                            '  Input (Data,Ary,Abs)                         ************
Data &HC0                                                   'End Collection                                 ************
Data &H05 , &H01                                            'Usage Page (Generic Desktop)                   ************
Data &H09 , &H80                                            'Usage (System Control)  * Управление питанием  ************
Data &HA1 , &H01                                            'Collection (Application)                       ************
Data &H85 , &H02                                            '  Report ID (2)                                ************
Data &H19 , &H81                                            '  Usage Minimum (System Power Down)            ************
Data &H29 , &H83                                            '  Usage Maximum (System Wake Up)               ************
Data &H25 , &H01                                            '  Logical Maximum (1)                          ************
Data &H75 , &H01                                            '  Report Size (1)                              ************
Data &H95 , &H03                                            '  Report Count (3)                             ************
Data &H81 , &H02                                            '  Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)  ************
Data &H95 , &H05                                            '  Report Count (5)                             ************
Data &H81 , &H01                                            '  Input (Cnst,Ary,Abs)                         ************
Data &HC0                                                   'End Collection                                 ************

'#endif

'*****************************String descriptors********************************
' Yes, they MUST be written like "t","e","s","t".  Doing so pads them with
' 0's.  If you write it like "test," I promise you it won't work.
' Нужно писать так: "t","e","s","t".
' Если написать "test," - работать не будет

'Default language descriptor (index 0)
'Дескриптор языка по умолчанию (индекс 0)
_usb_langdescriptor:
Data 4 , 4 , _usb_desc_string , 09 , 04                     '&h0409 = English
'Data 4 , 4 , _usb_desc_string , 19 , 04                     '&h0419 = Русский

'Manufacturer Descriptor (unicode)
'Дескриптор изготовителя (unicode)
_usb_mandescriptor:
' Radan & MrShilov
Data 34 , 34 , _usb_desc_string
Data &H52 , &H00 , &H61 , &H00 , &H64 , &H00 , &H61 , &H00 , &H6E , &H00
Data &H20 , &H00 , &H26 , &H00 , &H20 , &H00 , &H4D , &H00 , &H72 , &H00
Data &H53 , &H00 , &H68 , &H00 , &H69 , &H00 , &H6C , &H00 , &H6F , &H00
Data &H76 , &H00 , &H00 , 0

'Product Descriptor (unicode)
'Дескриптор продукта (unicode)
_usb_proddescriptor:
'Атомная клавиатура виндуксоида v.2
Data 70 , 70 , _usb_desc_string
Data &H10 , &H04 , &H42 , &H04 , &H3E , &H04 , &H3C , &H04 , &H3D , &H04
Data &H30 , &H04 , &H4F , &H04 , &H20 , &H00 , &H3A , &H04 , &H3B , &H04
Data &H30 , &H04 , &H32 , &H04 , &H38 , &H04 , &H30 , &H04 , &H42 , &H04
Data &H43 , &H04 , &H40 , &H04 , &H30 , &H04 , &H20 , &H00 , &H32 , &H04
Data &H38 , &H04 , &H3D , &H04 , &H34 , &H04 , &H43 , &H04 , &H3A , &H04
Data &H41 , &H04 , &H3E , &H04 , &H38 , &H04 , &H34 , &H04 , &H30 , &H04
Data &H20 , &H00 , &H76 , &H00 , &H2E , &H00 , &H32 , &H00 , &H00 , 0

'Дескриптор номера
_usb_numdescriptor:
Data 4 , 4 , _usb_desc_string
Data "2" , 0 , 0

'*******************************************************************************
'************************* Subroutines - Подпрограммы ***************************
'*******************************************************************************

Sub Usb_processsetup(txstate As Byte)
Senddescriptor = 0

   'Control transfers reset the sync bits like so
   Txstate = _usb_setup_sync

   'These are the standard device, interface, and endpoint requests that the
   'USB spec requires that we support.
   Select Case _usb_rx_buffer(2)
      'Стандартные запросы устройств
      Case &B10000000:
         Select Case _usb_rx_buffer(3)
           ' Case _usb_req_get_status:                       ' 00 - Определение состояния устройства

            Case _usb_req_get_descriptor:
               Select Case _usb_rx_buffer(5)
                  Case _usb_desc_device:
                     'Отправка дескриптора устроства
                     #if _usb_use_eeprom = 1
                        Readeeprom _usb_eepromaddrl , _usb_devicedescriptor
                     #else
                        Restore _usb_devicedescriptor
                     #endif
                     Senddescriptor = 1
                  Case _usb_desc_config:
                     'Отправка дескриптора конфигурации
                     #if _usb_use_eeprom = 1
                        Readeeprom _usb_eepromaddrl , _usb_configdescriptor
                     #else
                        Restore _usb_configdescriptor
                     #endif
                     Senddescriptor = 1
                  Case _usb_desc_string:
                     Select Case _usb_rx_buffer(4)
                        Case 0:
                           'Отправка дескриптора выбраного языка
                           #if _usb_use_eeprom = 1
                              Readeeprom _usb_eepromaddrl , _usb_langdescriptor
                           #else
                              Restore _usb_langdescriptor
                           #endif
                           Senddescriptor = 1
                        Case 1:
                           'Отправка дескриптора изготовителя
                           #if _usb_use_eeprom = 1
                              Readeeprom _usb_eepromaddrl , _usb_mandescriptor
                           #else
                              Restore _usb_mandescriptor
                           #endif
                           Senddescriptor = 1
                        Case 2:
                           'Отправка дескриптора продукта
                           #if _usb_use_eeprom = 1
                              Readeeprom _usb_eepromaddrl , _usb_proddescriptor
                           #else
                              Restore _usb_proddescriptor
                           #endif
                           Senddescriptor = 1
                        Case 3:
                           'Отправка дескриптора номера
                           #if _usb_use_eeprom = 1
                              Readeeprom _usb_eepromaddrl , _usb_numdescriptor
                           #else
                              Restore _usb_numdescriptor
                           #endif
                           Senddescriptor = 1

                     End Select
               End Select
'            CASE _usb_REQ_GET_CONFIG:
         End Select
      Case &B00000000:
         Select Case _usb_rx_buffer(3)
'            CASE _usb_REQ_CLEAR_FEATURE: ' 01 Сброс устройства
'            CASE _usb_REQ_SET_FEATURE:   ' 03 Установить свойство
            Case _usb_req_set_address:
               'USB status reporting for control writes
               Call Usb_send(txstate , 0)
               While Txstate._usb_txc = 0 : Wend
               'We are now addressed.
               _usb_deviceid = _usb_rx_buffer(4)
'            CASE _usb_REQ_SET_DESCRIPTOR:
            Case _usb_req_set_config:
               'Have to do status reporting
               Call Usb_send(txstate , 0)
         End Select
      'Стандартные запросы интерфейса
      Case &B10000001:
         Select Case _usb_rx_buffer(3)
'            CASE _usb_REQ_GET_STATUS:
'            CASE _usb_REQ_GET_IFACE:
            Case _usb_req_get_descriptor
            '_usb_rx_buffer(4) Индекс дескриптора и (5) его тип
               Select Case _usb_rx_buffer(5)
                  Case _usb_desc_report:
                     #if _usb_use_eeprom = 1
                        Readeeprom _usb_eepromaddrl , _usb_hid_reportdescriptor
                     #else
                        'Restore _usb_hid_reportdescriptor
                        If _usb_rx_buffer(6) = 0 Then Restore _usb_hid_reportdescriptor       'Первый интерфейс  ****************
                        If _usb_rx_buffer(6) = 1 Then Restore _usb_hid_reportdescriptor1       'Второй интерфейс ****************
                     #endif
                     Senddescriptor = 1

'                  CASE _usb_DESC_PHYSICAL

'                  CASE _USB_DESC_HID

               End Select
         End Select
      Case &B00100001:
         'Class specific SET requests
         Select Case _usb_rx_buffer(3)

            'Управление состоянием светодиодов NumLock, CapsLock и ScrollLock ****************************************************
            Case _usb_req_set_report:                       '*********************************************************************
               _usb_status._usb_rxc = 0                     '*********************************************************************
               _usb_status._usb_rtr = 1                     '*********************************************************************
               _usb_status2._usb_ignore = 0                 '*********************************************************************
               'Do status reporting                          '********************************************************************
               Call Usb_send(txstate , 0)                   '********************************************************************
               Do                                           '********************************************************************
               Loop Until _usb_status._usb_rxc = 1          '*******************************************************************
               Portd.0 = _usb_rx_buffer(2).0                'Состояние светодиодного индикатора NumLock    ***********************
 '              Portd.1 = _usb_rx_buffer(2).1                'Состояние светодиодного индикатора CapsLock   ***********************
               Portd.3 = _usb_rx_buffer(2).2                'Состояние светодиодного индикатора ScrollLock ***********************

            Case _usb_req_set_idle:
               Idlemode = 1
               'Do status reporting
               Call Usb_send(txstate , 0)
            'CASE _usb_REQ_SET_PROTOCOL:
         End Select
   End Select

   If Senddescriptor = 1 Then
      Call Usb_senddescriptor(txstate , _usb_rx_buffer(8))
   End If

End Sub

Sub Usb_senddescriptor(txstate As Byte , Maxlen As Byte)

   'Break the descriptor into packets and send to TxState
   Local Size As Byte
   Local I As Byte
   Local J As Byte
   Local Timeout As Word

   #if _usb_use_eeprom = 1
      'EEPROM access is a little funky.  The size has already been fetched
      'and stored in _usb_EEPROMADDRL, and the address of the descriptor
      'is now in the EEAR register pair.

      Size = _usb_eepromaddrl

      'Fetch the location of the descriptor and use it as an address pointer
      push R24
      in R24, EEARL
      sts {_USB_EEPROMADDRL}, R24
      in R24, eearH
      sts {_USB_EEPROMADDRH}, R24
      pop R24

   #else
      Read Size
   #endif


   If Maxlen < Size Then Size = Maxlen

   I = 2
   For J = 1 To Size
      Incr I
      #if _usb_use_eeprom = 1
         Incr _usb_eepromaddr
         Readeeprom Txstate(i) , _usb_eepromaddr
      #else
         Read Txstate(i)
      #endif

      If I = 10 Or J = Size Then
         I = I - 2
         Call Usb_send(txstate , I)
         While Txstate._usb_txc = 0
            Timeout = 0
            'To prevent an infinite loop, check for reset here
            While _usb_pin._usb_dminus = 0
               Incr Timeout
               If Timeout = 1000 Then                       '
                  Call Usb_reset()
                  Exit Sub
               End If
            Wend
         Wend
         I = 2
      End If
   Next
End Sub

Sub Usb_send(txstate As Byte , Byval Count As Byte)

   'Calculates and adds the CRC16,adds the DATAx PID,
   'and signals to the ISR that the data is ready to be sent.
   '
   '"Count" is the DATA payload size.  Range is 0 to 8. Do not exceed 8!

   'Reset all the flags except TxSync and RxSync
   Txstate = Txstate And _usb_syncmask
   'Calculate the 16-bit CRC
   _usb_crc = 0
   If Count <> 0 Then
      _usb_crc = Crc16uni(txstate(3) , Count , &HFFFF , &H8005 , 1 , 1)
      Toggle _usb_crc
   End If
   'Bytes to transmit will be PID + DATA payload + CRC16
   Count = Count + 3
   Txstate = Txstate + Count
   Txstate(count) = Low(_usb_crc)
   Incr Count
   Txstate(count) = High(_usb_crc)
   'Add the appropriate DATAx PID
   Txstate(2) = _usb_pid_data1
   If Txstate._usb_txsync = 0 Then
      Txstate(2) = _usb_pid_data0
   End If
   'The last step is to signal that the packet is Ready To Transmit
   Txstate._usb_rtt = 1
   Txstate._usb_txc = 0
End Sub

Sub Usb_reset()
   'Reset the receive flags
   _usb_status._usb_rtr = 1
   _usb_status._usb_rxc = 0
   'Reset the transmit flags
   _usb_tx_status = _usb_endp_init
   #if Varexist( "_usb_Endp2Addr")
   _usb_tx_status2 = _usb_endp_init
   #endif
   #if Varexist( "_usb_Endp3Addr")
   _usb_tx_status3 = _usb_endp_init
   #endif
   'Reset the device ID to 0
   _usb_deviceid = 0
   Idlemode = 0
End Sub

'******************** Действие по срабатыванию таймера 1 ***********************
Setflag:
'Нужно настроить на 12,5 Гц?!
Timer1 = 60000
  Flaginputmsg = 1
Return

0

3

Другой кварц пробовал. Точно так же.

Хотел всех перехитрить и сделать перезапуск с пульта подключив подтяжку D- 1k5 к порту.
Когда устройство работает перезапуск тоже, как отпадет перезапуск не работает. Отключается с характерным виндосовским звуком а обратно пишет что устройство неопределено.
Помогает только передергивание штеккера USB.

0

4

Испытал третий кварц на всякий случай. Эффект тот же.
http://s4.uploads.ru/t/f5wW7.jpg

Интересно почему каждый раз через 5 минут начинается какая то движуха а с обычной USB клавой нет.

Отредактировано Димон (2013-09-13 22:00:05)

0

5

Другое устройство (на макетке) ведет себя точно также.

0

6

Не удивительно что отваливается - в коде много задержек, общим временем, превышающих 10 миллисекунд (именно с таким периодом, комп опрашивает девайс и ждет от него ответа).

0

7

Хотелось бы по конкретнее по поводу задержек.

0

8

Зачем нужны строки

Код:
Waitms Paus

находящиеся после обработки очередной команды?

Вот этот код точно не перезагрузит USB.

Код:
If Command = 38 Then                                        ' restart USB
 Led = 1
  Ddrd.1 = 0
  Portd.1 = 0
   Waitms 1000
      Waitms 1000
         Waitms 1000
  Ddrd.1 = 1
  Portd.1 = 1
 Led = 0
End If

Это все равно что заставить зависнуть комп на пару секунд и сказать что он был перезагружен.

0

9

Код:
Waitms Paus

Этот код выполняется только после нажатия клавиши, а отпад происходит после простоя более 5 минут.(в это время данная часть кода не задействована)

Пробовал делать автоматические посылки нулей каждые 1,5 минуты - устройство полностью не отпадает (отпадает только его мультимедийная часть!)

0

10

Посылаю каждые 1,5 минуты код отжатия клавиши с нулями простой клавиатуры - отрубается только мультимедийная,

посылаю код мультимедийной - отрубаются только простые клавиши (мультимедийные работают)

посылаю коды обеих клавиатур - всё равно одна какая то отрубается.

Зато рестарт поправил, теперь с пульта могу переподключить отпавшее устройство. (смешно но всё же хоть что-то)

0

11

Всётаки если передавать по очереди код с одной и другой клавиатуры то работают обе.
Уже 45 минут пашет.

0

12

Пробовал другой шнур компьютер конденсаторы кварц контроллер. Всю тоже.
Ваша мультимедийная клава нормально себя ведет?

0

13

Оригинальная также. Не смог только прошивку  Radan -а в чистом виде попробовать. Нет у меня кварца на 15

0

14

http://s4.uploads.ru/t/FX9Bq.jpg
http://s4.uploads.ru/t/b2GsK.jpg
http://s5.uploads.ru/t/Fs4Lr.jpg

Пленка для лазерника, двухсторонний скотч и вспененный ПВХ 4мм.

Жаль кнопочек только две оказалось.

0

15

Глюк был из-за работы вот этого таймера и того, что с ним связано.

Код:
'Настроим таймер
Config Timer1 = Timer , Prescale = 256
On Timer1 Setflag
Enable Timer1
.....
....
....
'******************** Действие по срабатыванию таймера 1 ***********************
'Setflag:
'Нужно настроить на 12,5 Гц?!
'Timer1 = 60000
'  Flaginputmsg = 1
'Return

Отредактировано Димон (2013-09-19 21:17:19)

0

16

Вот рабочий код с пультом RC5, четырьмя кнопками и энкодером.

Код:
'*******************************************************************************
'----------------------- Мультимедиа-Клавиатура HID на USB ---------------------
'*******************************************************************************
'
'                                Bascom -avr V.2.0.4.0
'                                  Rubashka Vasiliy
'                                      Ukraine
'                                       2011
'                             Combined by MrShilov © 2012
'
'$prog &HFF , &HFF , &HD9 , &HFF                             'Take care that the chip supports all fuse bytes.


$noramclear
$hwstack = 40
$swstack = 40
$framesize = 50
$regfile = "m8def.dat"                                      'ATMEGA8-16PU
$crystal = 12000000                                         'Кварц - был 15МГц, заменен на 12МГц !!!!!!!!!!!!!!!!

'Include the software USB library - NEW
$lib "swusb.lbx"
$external _swusb

Declare Sub Usb_reset()
Declare Sub Usb_processsetup(txstate As Byte)
Declare Sub Usb_send(txstate As Byte , Byval Count As Byte)
Declare Sub Usb_senddescriptor(txstate As Byte , Maxlen As Byte)

'*************************** Конфигурация USB **********************************
'
'Set the following parameters to match your hardware configuration and USB
'device parameters.

'******************************* USB Connections *******************************

'Define the AVR port that the two USB pins are connected to
_usb_port Alias Portd
_usb_pin Alias Pind
_usb_ddr Alias Ddrd



'Define the D+ and D- pins. (put D+ on an interrupt pin)
Const _usb_dplus = 2
Const _usb_dminus = 4


'          +--*--------------*---------*--------------------+
'       0,1|  |              |         |    ATMEGA 8        |
'         --- |        +-----+---[1k5]-+    +--\/--+        |
'   USB   --- |        |     +---[10k]---*--|1   28|        |
'          |  |   CAPS | +--|<|--[300]---+--|2   27|        |
'  /---\   |  |   NUM  | *--|<|--[300]---+--|3   26|        |
' | VCC|-1-+--+ +------+-+-------[68 ]---+--|4   25|        |
'  \   |   |    | LOCK | *--|<|--[300]---+--|5   24|        |
'   |D-|-2-+--*-+------*-+-------[68 ]---+--|6   23|        |
'   |  |   |  | |        |            +--+--|7   22|--------+-+
'   |D+|-3-+--+-*-L<|----*------------+--+--|8   21|        | |
'  /   |   |  |          | +----------+--+--|9   20|--------* |
' | GND|-4-*  +---L<|----* |  ===  +--+--+--|10  19|------+ | |
'  \---/   |    2x3,6v   | +-12MHz-+  |  |  |11  18|----+ | | |
'          |             |    ===     |  |  |12  17|--+ | | | |
'          +-------------*--|<|--[300]+--+--|13  16|  | | | | |
'                        |STATUS      |  |  |14  15|  | | | | |
'                        |            |  |  +------+  | | | | |
'                        |            |  +----------+ | | | | |
'                        |            *-------*-----+-+-+-+-* |
'                        |            |0,1   +|22,0 | | | | | |
'                        |           ---     ---    | | | | | |
'                        |           ---     ---    | | | | | |
'                        |            |       |     | | | | | |
'                        *------------*-------*-----+-+-+-+-+-*
'                        |                          | | | | | |
'                       ===                         V V V V V V
'
'                                                   R M M S V G
'                                                   E O I C C N
'                                                   S S S K C D

'Configure the pins as inputs

Ddrb = &B11110011                                           'направление линий порта B: 1 - на вывод
Portb = &B00011111                                          'исходное состояние линий B: 00000000
Ddrc = &B00000000                                           'направление линий порта C: 1 - на вывод
Portc = &B11111111                                          'исходное состояние линий C: 00000000
Ddrd = &B11101011                                           'направление линий порта D: 1 - на вывод
Portd = &B00000000                                          'исходное состояние линий D: 00000000


Config Pinb.0 = Output                                      ' энкодер
Config Pinb.1 = Input
Config Pinb.2 = Input
Portb = 255
Config Rc5 = Pind.3
Config Pind.3 = Input
Config Portc.1 = Output
Config Portd.1 = Output
Portd.1 = 1                                                 '
Portb.1 = 1                                                 '
Portb.2 = 1                                                 '

'disable pullups
_usb_port._usb_dplus = 0
_usb_port._usb_dminus = 0

'************************* USB константы конфигурации **************************

'Использовать EEPROM или FLASH для хранения USB дескрипторов
'1 = EEPROM, 0 = FLASH.  Использование EEPROM немного уменьшит размер кода.
Const _usb_use_eeprom = 0

'Don't wait for sent packets to be ACK'd by the host before marking the
'transmission as complete.  This option breaks the USB spec but improves
'throughput with faster polling speeds.
'This may cause reliability issues.  Should leave set to 0 to be safe.
Const _usb_assume_ack = 0

'***************************** Дескриптор устройства****************************

'USB Vendor ID and Product ID (Assigned by USB-IF)
Const _usb_vid = &HBBBB
Const _usb_pid = &HEF33

'USB Device Release Number (BCD)
Const _usb_devrel = &H0001

'USB Release Spec (BCD)
Const _usb_spec = &H0110

'USB Device Class, subclass, and protocol (assigned by USB-IF).
'&h00 = Class defined by interface. (HID is defined in the interface)
'&hFF = Vendor-defined class (You must write your own PC driver)
'See http://www.usb.org/developers/defined_class  for more information
Const _usb_devclass = 0
Const _usb_devsubclass = 0
Const _usb_devprot = 0

'These are _indexes_ to UNICODE string descriptors for the manufacturer,
'product name, and serial number.  0 means there is no descriptor.
Const _usb_imanufacturer = 1
Const _usb_iproduct = 2
Const _usb_iserial = 0

'Количество конфигураций для этого устройства.  Не изменяйте это если,
'вы не знаете то, что Вы делаете!  Обычно равно 1
Const _usb_numconfigs = 1

'***************************** Конфигурация дискиптора *************************

'Количество интерфейсов для этого устройства (Обычно 1)
'Const _usb_numifaces = 1
Const _usb_numifaces = 2                                    'Теперь у нас 2 интерфейса !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

'Номер конфигурации (не редактировать!)
Const _usb_confignum = 1

'Индекс дескриптора строки УНИКОДА, который описывает эту конфигурацию (0 - отсутствует)
'Const _usb_iconfig = 2
Const _usb_iconfig = 0                                      'Не требуется !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

'&H80 = Устройство питается от шины USB.
'&HC0 = Устройство имеет свой источник питания.
'Const _usb_powered = &H80
Const _usb_powered = &HA0                                   'Питание от шины USB с возможностью "будить" компьютер !!!!!!!!!

'Потребляемый устройством ток * 2mA  (500mA max)
Const _usb_maxpower = 150                                   '50 * 2mA = 100mA

'**************************** Дескрипторы интерфейса ***************************

'Число интерфейсов для этого устройства (1 или 2)
'Const _usb_ifaces = 1
Const _usb_ifaces = 2                                       'Теперь у нас 2 интерфейса !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

'Номер интерфейса
Const _usb_ifaceaddr = 0
Const _usb_ifaceaddr1 = 1                                   'Индекс адреса второго интерфейса ******************************

'Альтернативный индекс
Const _usb_alternate = 0
Const _usb_alternate1 = 0                                   'У второго интерфейса тот же альтернативный адрес **************

'Количество конечных точек для этого интерфейса (исключая  нулевую)
'Const _usb_ifaceendpoints = 2
Const _usb_ifaceendpoints = 1                               'Одна точка для первого интерфейса !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Const _usb_ifaceendpoints1 = 1                              'Одна точка для второго интерфейса *****************************

'USB класс интерфейса, подкласс, и протокол (назначенное USB-IF).
'&h00 = RESERVED
'&hFF = Vendor-defined class (You must write your own PC driver)
'       Other values are USB interface device class. (such as HID)
'See http://www.usb.org/developers/defined_class  for more information
Const _usb_ifclass = 3
Const _usb_ifclass1 = 3                                     'Второй интерфейс тоже по прерыванию ***************************

'Const _usb_ifsubclass = 0
Const _usb_ifsubclass = 1                                   'Для клавиатуры субкласс 1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Const _usb_ifsubclass1 = 0                                  'Для мультимедиа субкласс 0 ************************************

'Const _usb_ifprotocol = 0
Const _usb_ifprotocol = 1                                   'Для клавиатуры протокол 1
Const _usb_ifprotocol1 = 0                                  'Для мультимедиа протокол 0

'Индекс в дескрипторе строки УНИКОДА для этого интерфейса (0 - отсутствует)
Const _usb_iiface = 0
Const _usb_iiface1 = 0                                      'Для мультимедиа тоже отсутствует ******************************
'*************************** Дополнительный HID дескриптор *********************
'HID класс, устройств являются вещами подобно клавиатуре, мыши, джойстику.
'See http://www.usb.org/developers/hidpage/  for the specification,
'tools, and resources.

'Учтите, что для устройства HID, класс устройства, подкласс, и протокол
'должен быть 0. Класс интерфейса должен быть 3 (HID).
'Подкласс Интерфейса и протокола должны быть 0 если Вы не делаете
'клавиатурой или мышь, которые поддерживают встроенный протокол.
'Смотрите страницы 8 и 9 спецификации HID 1.11 PDF.

'Число HID дескриптора  (EXCLUDING report and physical)
'Если Вы не делаете устройство HID, тогда установите эту константу на 0
'Const _usb_hids = 1
Const _usb_hids = 2                                         'Общее количество HID теперь 2 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

'BCD HID releasenumber.  Current spec is 1.11
Const _usb_hid_release = &H0111

'Country code from page 23 of the HID 1.11 specifications.
'Usually the country code is 0 unless you are making a keyboard.
Const _usb_hid_country = 0

' Номер сообщения и физических дескрипторов для этого HID
' Должно быть в 1! Все HID устройства иметь по крайней мере 1 дескриптор сообщения.
Const _usb_hid_numdescriptors = 1

'Use a software tool to create the report descriptor and $INCLUDE it.


'*************************** Дескриптор конечной точки *************************

'Конечная точка 0 не включается здесь.  Эти - только для других
'конечных точек.
'Примечание: HID устройства требуют 1 прерывание В конечной точке

'Адрес дополнительных конечных точек (Должно быть > 0. сделать  комментарием, если не требуется)
Const _usb_endp2addr = 1
Const _usb_endp3addr = 2

'Правильные типы - 0 для управления или 3 для прерывания
Const _usb_endp2type = 3
Const _usb_endp3type = 3

'Направление: 0=Out (от компа), 1=In (в комп). Проигнорированно управляющими конечными точками
Const _usb_endp2direction = 1
'Const _usb_endp3direction = 0
Const _usb_endp3direction = 1                               'Теперь и вторая точка тоже из МК в ПК !!!!!!!!!!!!!!!!!!!!!!!!

' Интервал опроса (мс) для конечных точек прерывания.
' Проигнорированно управляющими конечными точками
' (Должно быть не менее 10)
Const _usb_endp2interval = 10
Const _usb_endp3interval = 10

'*******************************************************************************
'The includes need to go right here--between the configuration constants above
'and the start of the program below.  The includes will automatically calculate
'constants based on the above configuration, dimension required variables, and
'allocate transmit and receive buffers.  Nothing inside the includes file needs
'to be modified.
$include "Const_swusb-includes.bas"
'*******************************************************************************

'**************************** USB Interrupt And Init ***************************
'Инициализация всех переменных, флагов, и бит синхронизации
Init:
Call Usb_reset()
Const _usb_intf = Intf0
Config Int0 = Rising
On Int0 Usb_isr Nosave
Enable Int0

Enable Interrupts                                           'Разрешить все прерывания

'*************************** Завершение концигурации USB ***********************
'*******************************************************************************
Led Alias Portc.1
Dim Resetcounter As Word
Dim Idlemode As Byte
Dim Flaginputmsg As Byte                                    'Флаг срабатывания таймера
Dim Key_code(2) As Byte                                     'Передаваемый репорт (8 байт)
Dim M_key_code(3) As Byte                                   'Массив состояния клавиш
Dim Key(4) As Byte                                          'Массив предыдущего состояния клавиш
Dim K As Byte                                               'Счётчик цикла сканирования клавиш
Dim Paus As Byte                                            'Пауза между передаваемыми символами
Dim B1 As Byte
Dim Address As Byte , Command As Byte
Dim Tic_rc5 As Integer
Paus = 50

'Помигаем светодиодом статуса - контроллер стартовал
'Tic = 0
Led = 1
Waitms 100
Led = 0
Waitms 300
Led = 1
Waitms 100
Led = 0
Waitms 300
Led = 1
Waitms 100
Led = 0

' Формат передаваемого репорта  - usb_tx_buffer:

   _usb_tx_buffer2(2) = 0                                   ' modifier    - комбинация из 8-ми модификаций (левые и правые Ctrl, Alt, Shift, Win)
   _usb_tx_buffer2(3) = 0                                   ' reserved    - резерв
   _usb_tx_buffer2(4) = 0                                   ' keycode 0 - код клавиши 0
   _usb_tx_buffer2(5) = 0                                   ' keycode 1 - код клавиши 1
   _usb_tx_buffer2(6) = 0                                   ' keycode 2 - код клавиши 2
   _usb_tx_buffer2(7) = 0                                   ' keycode 3 - код клавиши 3
   _usb_tx_buffer2(8) = 0                                   ' keycode 4 - код клавиши 4
   _usb_tx_buffer2(9) = 0                                   ' keycode 5 - код клавиши 5

' modifier
' bit0  LEFT CTRL   (1)
' bit1  LEFT SHIFT  (2)
' bit2  LEFT ALT    (4)
' bit3  LEFT WIN    (8)
' bit4  RIGHT CTRL  (16)
' bit5  RIGHT SHIFT (32)
' bit6  RIGHT ALT   (64)
' bit7  RIGHT WIN   (128)

' CTRL + ALT + DEL
' Эту комбинацию нужно передать так: &H05, &H00, &H4С, &H00, &H00, &H00, &H00, &H00 = 5[Ctrl(1) + Alt(4)], 0, 76, 0, 0, 0, 0, 0
' В первый байт попадает сумма модификаций клавиш (левые и правые Ctrl, Alt, Shift, Win)

'******************************* Основной цикл *********************************

Do

   Resetcounter = 0

   'Флаг сброса
   While _usb_pin._usb_dminus = 0
      Incr Resetcounter
      If Resetcounter = 1000 Then
         Call Usb_reset()
      End If
   Wend

   'Флаг полученных данных
   If _usb_status._usb_rxc = 1 Then

      If _usb_status._usb_setup = 1 Then
         'Обработка пакет/управление сообщения установки
         Call Usb_processsetup(_usb_tx_status)
      End If

      'Восстановление бита RXC и установка бита RTR (готовность получить новый пакет)
      _usb_status._usb_rtr = 1
      _usb_status._usb_rxc = 0
   End If
If Tic_rc5 > 10000 Then                                     'Отключение опроса RC5 во время работы энкодера (а то энкодер глючит)
  Getrc5(address , Command)
  If Address = 0 Then
   Command = Command And &B01111111                         'clear the toggle bit toggle bit is bit 7. Extended RC5 bit is in bit 6
  End If
Tic_rc5 = 10001
End If
Incr Tic_rc5
B1 = Encoder(pinb.1 , Pinb.2 , Links , Rechts , 0)          ' опрос энкодера
'*************************** СКАНИРУЕМ КЛАВИАТУРУ ******************************
 Key(1) = Pinc.2                                            'stop
 Key(2) = Pinc.3                                            'fwd
 Key(3) = Pinc.4                                            'play
 Key(4) = Pinc.5                                            'prew
'************************ команды RC5 ****************************
If Command = 38 Then                                        ' restart USB переподключение устройства с команды пульта (на всякий случай)
 Led = 1
  Ddrd.1 = 0
  Portd.1 = 0
   Waitms 1000
  Ddrd.1 = 1
  Portd.1 = 1
 Led = 0
Goto Init
End If

If Command = 12 Then                                        ' Power PC аппаратное вклюсение\выключение ПК (подключается отдельным проводом вместо кнопки вкыл через оптрон)
 Led = 1
  Portb.0 = 0
   Waitms 1000
  Portb.0 = 1
 Led = 0
End If

 If Command = 15 Then                                       ' Esc
  Key_code(1) = 0
  Key_code(2) = 40
  Gosub Send_key
 End If


 If Command = 63 Then
  M_key_code(1) = 1
  M_key_code(2) = 234                                       ' Volume-
  M_key_code(3) = 0
  Gosub Send_m_key
 End If

 If Command = 56 Then
  M_key_code(1) = 1
  M_key_code(2) = 233                                       ' Volume+
  M_key_code(3) = 0
  Gosub Send_m_key
 End If

 If Command = 55 Then
  Key_code(1) = 0
  Key_code(2) = 44                                          'Space
  Gosub Send_key
 End If

 If Command = 17 Then
  Key_code(1) = 0
  Key_code(2) = 80                                          'Left
  Gosub Send_key
 End If
 If Command = 16 Then
  Key_code(1) = 0
  Key_code(2) = 79                                          'Right
  Gosub Send_key
 End If

 If Command = 32 Then
  Key_code(1) = 0
  Key_code(2) = 82                                          'Up
  Gosub Send_key
 End If

 If Command = 33 Then
  Key_code(1) = 0
  Key_code(2) = 81                                          'Down
  Gosub Send_key
 End If

 If Command = 59 Then
  Key_code(1) = 0
  Key_code(2) = 40                                          'Enter
  Gosub Send_key
 End If

 If Command = 50 Then
   M_key_code(1) = 1
   M_key_code(2) = 183                                      '  Stop
   M_key_code(3) = 0
   Gosub Send_m_key
 End If

 If Command = 43 Then
   M_key_code(1) = 1
   M_key_code(2) = 205                                      '  Play/Pause
   M_key_code(3) = 0
   Gosub Send_m_key
   End If

 If Command = 13 Then
   M_key_code(1) = 1
   M_key_code(2) = 205                                      '  Play/Pause
   M_key_code(3) = 0
   Gosub Send_m_key
 End If
 If Command = 41 Then
   M_key_code(1) = 1
   M_key_code(2) = 181                                      ' next
   M_key_code(3) = 0
   Gosub Send_m_key
 End If
 If Command = 44 Then
   M_key_code(1) = 1
   M_key_code(2) = 182                                      ' Prew
   M_key_code(3) = 0
   Gosub Send_m_key
 End If


'*************** команды с клавиатуры ****************
 If Key(1) = 0 Then
   M_key_code(1) = 1
   M_key_code(2) = 183                                      '  Stop
   M_key_code(3) = 0
   Gosub Send_m_key
 End If

 If Key(3) = 0 Then
   M_key_code(1) = 1
   M_key_code(2) = 205                                      '  Play/Pause
   M_key_code(3) = 0
   Gosub Send_m_key
 End If

 If Key(2) = 0 Then
   M_key_code(1) = 1
   M_key_code(2) = 181                                      ' next
   M_key_code(3) = 0
   Gosub Send_m_key
 End If

 If Key(4) = 0 Then
   M_key_code(1) = 1
   M_key_code(2) = 182                                      ' Prew
   M_key_code(3) = 0
   Gosub Send_m_key
 End If



Loop
'*************************** Конец основного цикла *****************************
'**************************** Обработка энкодера ************************
Links:                                                      ' энкодер в лево
Tic_rc5 = 0                                                 'Отключение опроса RC5 (а то энкодер глючит)
Led = 1
     If _usb_tx_status._usb_txc = 1 Then                    'Volume -
             _usb_tx_buffer3(2) = 1
             _usb_tx_buffer3(3) = 234
             _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
          Waitms 5
     End If
    Bitwait _usb_tx_status._usb_txc , Set
     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer3(2) = 1                          ' Отжатие клавиш
            _usb_tx_buffer3(3) = 0
            _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
         Waitms 1
     End If
Led = 0
Return

Rechts:                                                     'энкодер в право
Tic_rc5 = 0                                                 'Отключение опроса RC5 (а то энкодер глючит)
Led = 1
     If _usb_tx_status._usb_txc = 1 Then                    'Volume +
             _usb_tx_buffer3(2) = 1
             _usb_tx_buffer3(3) = 233
             _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
          Waitms 5
     End If
    Bitwait _usb_tx_status._usb_txc , Set
     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer3(2) = 1                          ' Отжатие клавиш
            _usb_tx_buffer3(3) = 0
            _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
         Waitms 1
     End If
Led = 0
Return
'************************ Посылка кода в USB ***************************

Send_key:                                                   'Простые клавиши
Led = 1
     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer2(2) = Key_code(1)                '
            _usb_tx_buffer2(4) = Key_code(2)                '
           Call Usb_send(_usb_tx_status2 , 8)               ' Сообщение в компьютер
           Waitms Paus
     End If
     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer2(2) = 0                          ' Отжатие клавиш
            _usb_tx_buffer2(4) = 0
           Call Usb_send(_usb_tx_status2 , 8)               ' Сообщение в компьютер
           Waitms Paus
     End If
Led = 0
Return
Send_m_key:                                                 'Мультимедийные клавиши
Led = 1
     If _usb_tx_status._usb_txc = 1 Then                    '
             _usb_tx_buffer3(2) = M_key_code(1)             ' Нажатие клавиш
             _usb_tx_buffer3(3) = M_key_code(2)
             _usb_tx_buffer3(4) = M_key_code(3)
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
          Waitms Paus
     End If
    Bitwait _usb_tx_status._usb_txc , Set
     If _usb_tx_status._usb_txc = 1 Then
            _usb_tx_buffer3(2) = 1                          ' Отжатие клавиш
            _usb_tx_buffer3(3) = 0
            _usb_tx_buffer3(4) = 0
           Call Usb_send(_usb_tx_status3 , 3)               ' Сообщение в компьютер
         Waitms Paus
     End If
Led = 0

Return
End


'*******************************************************************************
'**************** Дескрипторы, сохранённые в EEPROM или FLASH ******************
'                     Не изменять порядок дескрипторов!
'
#if _usb_use_eeprom = 1
   $eeprom
#else
   $data
#endif

'Дескрипторы устройства
_usb_devicedescriptor:
Data 18 , 18 , _usb_desc_device , _usb_specl , _usb_spech , _usb_devclass
Data _usb_devsubclass , _usb_devprot , 8 , _usb_vidl , _usb_vidh , _usb_pidl
Data _usb_pidh , _usb_devrell , _usb_devrelh , _usb_imanufacturer
Data _usb_iproduct , _usb_iserial , _usb_numconfigs


'Retrieving the configuration descriptor also gets all the interface and
'endpoint descriptors for that configuration.  It is not possible to retrieve
'only an interface or only an endpoint descriptor.  Consequently, this is a
'large transaction of variable size.

_usb_configdescriptor:
Data _usb_descr_total , 9 , _usb_desc_config , _usb_descr_totall
Data _usb_descr_totalh , _usb_numifaces , _usb_confignum , _usb_iconfig
Data _usb_powered , _usb_maxpower

'_usb_IFaceDescriptor
Data 9 , _usb_desc_iface , _usb_ifaceaddr , _usb_alternate
Data _usb_ifaceendpoints , _usb_ifclass , _usb_ifsubclass , _usb_ifprotocol
Data _usb_iiface

'#if _usb_hids > 0
'_usb_HIDDescriptor
Data _usb_hid_descr_len , _usb_desc_hid , _usb_hid_releasel , _usb_hid_releaseh
Data _usb_hid_country , _usb_hid_numdescriptors

'Next follows a list of bType and wLength bytes/words for each report and
'physical descriptor.  There must be at least 1 report descriptor.  In practice,
'There are usually 0 physical descriptors and only 1 report descriptor.

Data _usb_desc_report
Data 63 , 0                                                 ' первое число должно быть таким же, как количество данных дескриптора HID - _usb_hid_reportdescriptor
'End of report/physical descriptor list
'#endif

'#if _usb_endpoints > 1
'_usb_EndpointDescriptor
Data 7 , _usb_desc_endpoint , _usb_endp2attr , _usb_endp2type , 8 , 0
Data _usb_endp2interval
'#endif

'_usb_IFaceDescriptor1 *************************************************************************************
Data 9 , _usb_desc_iface , _usb_ifaceaddr1 , _usb_alternate1       '                            ***********
Data _usb_ifaceendpoints1 , _usb_ifclass1 , _usb_ifsubclass1 , _usb_ifprotocol1       '         ***********
Data _usb_iiface1                                           '                                   ***********

'_usb_HIDDescriptor1  *************************************************************************************
Data _usb_hid_descr_len , _usb_desc_hid , _usb_hid_releasel , _usb_hid_releaseh       '         ***********
Data _usb_hid_country , _usb_hid_numdescriptors , _usb_desc_report       '                      ***********
Data 50 , 0                                                 'Длина мультимедиа-репорта 50 байт  ***********

'#if _usb_endpoints > 2
'_usb_EndpointDescriptor
'Data 7 , _usb_desc_endpoint , _usb_endp3attr , _usb_endp3type , 8 , 0
Data 7 , _usb_desc_endpoint , _usb_endp3attr , _usb_endp3type , 3 , 0       'Для мультимедиа длина сообщения 3 байта !!!!!!!!!!!!!!!!
Data _usb_endp3interval
'#endif

'#if _usb_hids > 0
_usb_hid_reportdescriptor:
Data 63                                                     'Количество данных дескриптора HID, установить такое же в _usb_desc_report
Data &H05 , &H01                                            '   USAGE_PAGE (Generic Desktop)
Data &H09 , &H06                                            '   USAGE (Keyboard)
Data &HA1 , &H01                                            '   COLLECTION (Application)
Data &H05 , &H07                                            '   USAGE_PAGE (Keyboard)
Data &H19 , &HE0                                            '   USAGE_MINIMUM (Keyboard LeftControl)
Data &H29 , &HE7                                            '   USAGE_MAXIMUM (Keyboard Right GUI)
Data &H15 , &H00                                            '   LOGICAL_MINIMUM (0)
Data &H25 , &H01                                            '   LOGICAL_MAXIMUM (1)
Data &H75 , &H01                                            '   REPORT_SIZE (1)
Data &H95 , &H08                                            '   REPORT_COUNT (8)
Data &H81 , &H02                                            '   INPUT (Data,Var,Abs) ** Modifier Byte **
Data &H95 , &H01                                            '   REPORT_COUNT (1)
Data &H75 , &H08                                            '   REPORT_SIZE (8)
Data &H81 , &H03                                            '   INPUT (Cnst,Var,Abs) ** Reserved Byte **
Data &H95 , &H05                                            '   REPORT_COUNT (5)
Data &H75 , &H01                                            '   REPORT_SIZE (1)
Data &H05 , &H08                                            '   USAGE_PAGE (LEDs)
Data &H19 , &H01                                            '   USAGE_MINIMUM (Num Lock)
Data &H29 , &H05                                            '   USAGE_MAXIMUM (Kana)
Data &H91 , &H02                                            '   OUTPUT (Data,Var,Abs) ** LED Report **
Data &H95 , &H01                                            '   REPORT_COUNT (1)
Data &H75 , &H03                                            '   REPORT_SIZE (3)
Data &H91 , &H03                                            '   OUTPUT (Cnst,Var,Abs) ** LED Report Padding **
Data &H95 , &H06                                            '   REPORT_COUNT (6) ** here we define the maximum number of simultaneous keystrokes we can detect **
Data &H75 , &H08                                            '   REPORT_SIZE (8)
Data &H15 , &H00                                            '   LOGICAL_MINIMUM (0)
Data &H25 , &H65                                            '   LOGICAL_MAXIMUM (101)
Data &H05 , &H07                                            '   USAGE_PAGE (Keyboard)
Data &H19 , &H00                                            '   USAGE_MINIMUM (Reserved (no event indicated))
Data &H29 , &H65                                            '   USAGE_MAXIMUM (Keyboard Application)
Data &H81 , &H00                                            '   INPUT (Data,Ary,Abs) ** Key arrays (6 bytes) **
Data &HC0                                                   '   END_COLLECTION

_usb_hid_reportdescriptor1:                                 '                                               ************
Data 50                                                     '                                               ************
Data &H05 , &H0C                                            'Usage Page (Consumer Devices)                  ************
Data &H09 , &H01                                            'Usage (Consumer Control) * Мультимедиа клавиши ************
Data &HA1 , &H01                                            'Collection (Application)                       ************
Data &H85 , &H01                                            '  Report ID (1)                                ************
Data &H19 , &H00                                            '  Usage Minimum (Undefined)                    ************
Data &H2A , &H3C , &H02                                     '  Usage Maximum (reserved 0x023c)              ************
Data &H15 , &H00                                            '  Logical Minimum (0)                          ************
Data &H26 , &H3C , &H02                                     '  Logical Maximum (572)                        ************
Data &H95 , &H01                                            '  Report Count (1)                             ************
Data &H75 , &H10                                            '  Report Size (16)                             ************
Data &H81 , &H00                                            '  Input (Data,Ary,Abs)                         ************
Data &HC0                                                   'End Collection                                 ************
Data &H05 , &H01                                            'Usage Page (Generic Desktop)                   ************
Data &H09 , &H80                                            'Usage (System Control)  * Управление питанием  ************
Data &HA1 , &H01                                            'Collection (Application)                       ************
Data &H85 , &H02                                            '  Report ID (2)                                ************
Data &H19 , &H81                                            '  Usage Minimum (System Power Down)            ************
Data &H29 , &H83                                            '  Usage Maximum (System Wake Up)               ************
Data &H25 , &H01                                            '  Logical Maximum (1)                          ************
Data &H75 , &H01                                            '  Report Size (1)                              ************
Data &H95 , &H03                                            '  Report Count (3)                             ************
Data &H81 , &H02                                            '  Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)  ************
Data &H95 , &H05                                            '  Report Count (5)                             ************
Data &H81 , &H01                                            '  Input (Cnst,Ary,Abs)                         ************
Data &HC0                                                   'End Collection                                 ************

'#endif

'*****************************String descriptors********************************
' Yes, they MUST be written like "t","e","s","t".  Doing so pads them with
' 0's.  If you write it like "test," I promise you it won't work.
' Нужно писать так: "t","e","s","t".
' Если написать "test," - работать не будет

'Default language descriptor (index 0)
'Дескриптор языка по умолчанию (индекс 0)
_usb_langdescriptor:
Data 4 , 4 , _usb_desc_string , 09 , 04                     '&h0409 = English
'Data 4 , 4 , _usb_desc_string , 19 , 04                     '&h0419 = Русский

'Manufacturer Descriptor (unicode)
'Дескриптор изготовителя (unicode)
_usb_mandescriptor:
' Radan & MrShilov
Data 34 , 34 , _usb_desc_string
Data &H52 , &H00 , &H61 , &H00 , &H64 , &H00 , &H61 , &H00 , &H6E , &H00
Data &H20 , &H00 , &H26 , &H00 , &H20 , &H00 , &H4D , &H00 , &H72 , &H00
Data &H53 , &H00 , &H68 , &H00 , &H69 , &H00 , &H6C , &H00 , &H6F , &H00
Data &H76 , &H00 , &H00 , 0

'Product Descriptor (unicode)
'Дескриптор продукта (unicode)
_usb_proddescriptor:
'Атомная клавиатура виндуксоида v.2
Data 70 , 70 , _usb_desc_string
Data &H10 , &H04 , &H42 , &H04 , &H3E , &H04 , &H3C , &H04 , &H3D , &H04
Data &H30 , &H04 , &H4F , &H04 , &H20 , &H00 , &H3A , &H04 , &H3B , &H04
Data &H30 , &H04 , &H32 , &H04 , &H38 , &H04 , &H30 , &H04 , &H42 , &H04
Data &H43 , &H04 , &H40 , &H04 , &H30 , &H04 , &H20 , &H00 , &H32 , &H04
Data &H38 , &H04 , &H3D , &H04 , &H34 , &H04 , &H43 , &H04 , &H3A , &H04
Data &H41 , &H04 , &H3E , &H04 , &H38 , &H04 , &H34 , &H04 , &H30 , &H04
Data &H20 , &H00 , &H76 , &H00 , &H2E , &H00 , &H32 , &H00 , &H00 , 0

'Дескриптор номера
_usb_numdescriptor:
Data 4 , 4 , _usb_desc_string
Data "2" , 0 , 0

'*******************************************************************************
'************************* Subroutines - Подпрограммы ***************************
'*******************************************************************************

Sub Usb_processsetup(txstate As Byte)
Senddescriptor = 0

   'Control transfers reset the sync bits like so
   Txstate = _usb_setup_sync

   'These are the standard device, interface, and endpoint requests that the
   'USB spec requires that we support.
   Select Case _usb_rx_buffer(2)
      'Стандартные запросы устройств
      Case &B10000000:
         Select Case _usb_rx_buffer(3)
           ' Case _usb_req_get_status:                       ' 00 - Определение состояния устройства

            Case _usb_req_get_descriptor:
               Select Case _usb_rx_buffer(5)
                  Case _usb_desc_device:
                     'Отправка дескриптора устроства
                     #if _usb_use_eeprom = 1
                        Readeeprom _usb_eepromaddrl , _usb_devicedescriptor
                     #else
                        Restore _usb_devicedescriptor
                     #endif
                     Senddescriptor = 1
                  Case _usb_desc_config:
                     'Отправка дескриптора конфигурации
                     #if _usb_use_eeprom = 1
                        Readeeprom _usb_eepromaddrl , _usb_configdescriptor
                     #else
                        Restore _usb_configdescriptor
                     #endif
                     Senddescriptor = 1
                  Case _usb_desc_string:
                     Select Case _usb_rx_buffer(4)
                        Case 0:
                           'Отправка дескриптора выбраного языка
                           #if _usb_use_eeprom = 1
                              Readeeprom _usb_eepromaddrl , _usb_langdescriptor
                           #else
                              Restore _usb_langdescriptor
                           #endif
                           Senddescriptor = 1
                        Case 1:
                           'Отправка дескриптора изготовителя
                           #if _usb_use_eeprom = 1
                              Readeeprom _usb_eepromaddrl , _usb_mandescriptor
                           #else
                              Restore _usb_mandescriptor
                           #endif
                           Senddescriptor = 1
                        Case 2:
                           'Отправка дескриптора продукта
                           #if _usb_use_eeprom = 1
                              Readeeprom _usb_eepromaddrl , _usb_proddescriptor
                           #else
                              Restore _usb_proddescriptor
                           #endif
                           Senddescriptor = 1
                        Case 3:
                           'Отправка дескриптора номера
                           #if _usb_use_eeprom = 1
                              Readeeprom _usb_eepromaddrl , _usb_numdescriptor
                           #else
                              Restore _usb_numdescriptor
                           #endif
                           Senddescriptor = 1

                     End Select
               End Select
'            CASE _usb_REQ_GET_CONFIG:
         End Select
      Case &B00000000:
         Select Case _usb_rx_buffer(3)
'            CASE _usb_REQ_CLEAR_FEATURE: ' 01 Сброс устройства
'            CASE _usb_REQ_SET_FEATURE:   ' 03 Установить свойство
            Case _usb_req_set_address:
               'USB status reporting for control writes
               Call Usb_send(txstate , 0)
               While Txstate._usb_txc = 0 : Wend
               'We are now addressed.
               _usb_deviceid = _usb_rx_buffer(4)
'            CASE _usb_REQ_SET_DESCRIPTOR:
            Case _usb_req_set_config:
               'Have to do status reporting
               Call Usb_send(txstate , 0)
         End Select
      'Стандартные запросы интерфейса
      Case &B10000001:
         Select Case _usb_rx_buffer(3)
'            CASE _usb_REQ_GET_STATUS:
'            CASE _usb_REQ_GET_IFACE:
            Case _usb_req_get_descriptor
            '_usb_rx_buffer(4) Индекс дескриптора и (5) его тип
               Select Case _usb_rx_buffer(5)
                  Case _usb_desc_report:
                     #if _usb_use_eeprom = 1
                        Readeeprom _usb_eepromaddrl , _usb_hid_reportdescriptor
                     #else
                        'Restore _usb_hid_reportdescriptor
                        If _usb_rx_buffer(6) = 0 Then Restore _usb_hid_reportdescriptor       'Первый интерфейс  ****************
                        If _usb_rx_buffer(6) = 1 Then Restore _usb_hid_reportdescriptor1       'Второй интерфейс ****************
                     #endif
                     Senddescriptor = 1

'                  CASE _usb_DESC_PHYSICAL

'                  CASE _USB_DESC_HID

               End Select
         End Select
      Case &B00100001:
         'Class specific SET requests
         Select Case _usb_rx_buffer(3)

            'Управление состоянием светодиодов NumLock, CapsLock и ScrollLock ****************************************************
            Case _usb_req_set_report:                       '*********************************************************************
               _usb_status._usb_rxc = 0                     '*********************************************************************
               _usb_status._usb_rtr = 1                     '*********************************************************************
               _usb_status2._usb_ignore = 0                 '*********************************************************************
               'Do status reporting                          '********************************************************************
               Call Usb_send(txstate , 0)                   '********************************************************************
               Do                                           '********************************************************************
               Loop Until _usb_status._usb_rxc = 1          '*******************************************************************
   '            Portd.0 = _usb_rx_buffer(2).0                'Состояние светодиодного индикатора NumLock    ***********************
 '              Portd.1 = _usb_rx_buffer(2).1                'Состояние светодиодного индикатора CapsLock   ***********************
 '              Portd.3 = _usb_rx_buffer(2).2                'Состояние светодиодного индикатора ScrollLock ***********************

            Case _usb_req_set_idle:
               Idlemode = 1
               'Do status reporting
               Call Usb_send(txstate , 0)
            'CASE _usb_REQ_SET_PROTOCOL:
         End Select
   End Select

   If Senddescriptor = 1 Then
      Call Usb_senddescriptor(txstate , _usb_rx_buffer(8))
   End If

End Sub

Sub Usb_senddescriptor(txstate As Byte , Maxlen As Byte)

   'Break the descriptor into packets and send to TxState
   Local Size As Byte
   Local I As Byte
   Local J As Byte
   Local Timeout As Word

   #if _usb_use_eeprom = 1
      'EEPROM access is a little funky.  The size has already been fetched
      'and stored in _usb_EEPROMADDRL, and the address of the descriptor
      'is now in the EEAR register pair.

      Size = _usb_eepromaddrl

      'Fetch the location of the descriptor and use it as an address pointer
      push R24
      in R24, EEARL
      sts {_USB_EEPROMADDRL}, R24
      in R24, eearH
      sts {_USB_EEPROMADDRH}, R24
      pop R24

   #else
      Read Size
   #endif


   If Maxlen < Size Then Size = Maxlen

   I = 2
   For J = 1 To Size
      Incr I
      #if _usb_use_eeprom = 1
         Incr _usb_eepromaddr
         Readeeprom Txstate(i) , _usb_eepromaddr
      #else
         Read Txstate(i)
      #endif

      If I = 10 Or J = Size Then
         I = I - 2
         Call Usb_send(txstate , I)
         While Txstate._usb_txc = 0
            Timeout = 0
            'To prevent an infinite loop, check for reset here
            While _usb_pin._usb_dminus = 0
               Incr Timeout
               If Timeout = 1000 Then                       '
                  Call Usb_reset()
                  Exit Sub
               End If
            Wend
         Wend
         I = 2
      End If
   Next
End Sub

Sub Usb_send(txstate As Byte , Byval Count As Byte)

   'Calculates and adds the CRC16,adds the DATAx PID,
   'and signals to the ISR that the data is ready to be sent.
   '
   '"Count" is the DATA payload size.  Range is 0 to 8. Do not exceed 8!

   'Reset all the flags except TxSync and RxSync
   Txstate = Txstate And _usb_syncmask
   'Calculate the 16-bit CRC
   _usb_crc = 0
   If Count <> 0 Then
      _usb_crc = Crc16uni(txstate(3) , Count , &HFFFF , &H8005 , 1 , 1)
      Toggle _usb_crc
   End If
   'Bytes to transmit will be PID + DATA payload + CRC16
   Count = Count + 3
   Txstate = Txstate + Count
   Txstate(count) = Low(_usb_crc)
   Incr Count
   Txstate(count) = High(_usb_crc)
   'Add the appropriate DATAx PID
   Txstate(2) = _usb_pid_data1
   If Txstate._usb_txsync = 0 Then
      Txstate(2) = _usb_pid_data0
   End If
   'The last step is to signal that the packet is Ready To Transmit
   Txstate._usb_rtt = 1
   Txstate._usb_txc = 0
End Sub

Sub Usb_reset()
   'Reset the receive flags
   _usb_status._usb_rtr = 1
   _usb_status._usb_rxc = 0
   'Reset the transmit flags
   _usb_tx_status = _usb_endp_init
   #if Varexist( "_usb_Endp2Addr")
   _usb_tx_status2 = _usb_endp_init
   #endif
   #if Varexist( "_usb_Endp3Addr")
   _usb_tx_status3 = _usb_endp_init
   #endif
   'Reset the device ID to 0
   _usb_deviceid = 0
   Idlemode = 0
End Sub

'******************** Действие по срабатыванию таймера 1 ***********************
'Setflag:
'Нужно настроить на 12,5 Гц?!
'Timer1 = 60000
'  Flaginputmsg = 1
'Return

Отредактировано Димон (2013-09-19 21:29:16)

0