16FUSB или софтварный USB на младших PIC-ах

8-битные микроконтроллеры PICmicro (ПИКи) от Microchip и совместимые, а также 16-битные PIC24 и 32-битные PIC32

Moderator: Shaos

User avatar
Lavr
Supreme God
Posts: 16680
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

Tronix wrote:там обработка USB завязана на высчитанные предварительно машинные такты. Увеличиваем частоту - все расчеты сдвигаются...
Ну ясен пень, что программу перетрясти придётся на другой частоте, я вобщем-то предполагал...

Если не трудно - замерь всё же максимальную частоту, а то я давно уже купил вот такую хрень usb2lpt:

Image
Gembird USB to Bitronics Converter

но "лапками шевелить" она, как оказалось, не умеет... :(
iLavr
Tronix
Doomed
Posts: 662
Joined: 18 Nov 2013 02:38
Location: Москва

Post by Tronix »

Попробуем глянуть. Вот я думаю, может буферизацию сделать байт на 64? С другой стороны вряд-ли спасет положение... Надо менять на хардварный USB.
User avatar
Lavr
Supreme God
Posts: 16680
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

Есть ещё 2 трюка, которые могут помочь сравнительно просто организовать параллельный интерфейс.

Первый трюк - с "прошивочными и интерфейсными" USB-кабелями для сотовых телефонов:
они по сути представляют собой переходники USB-2-COM, причем сигналы RS-232 у них
5-вольтовые, а с точки зрения Венды они встают как COM-порты.
Причем, иногда позволяют использовать скорость обмена, большую, нежели максимальная,
устанавливаемая в Венде.

Я через два таких кабеля, соединенных RS-232-выводами соединял 2 компьютера по USB-портам,
как по COM-портам.

Так вот, если есть PIC или др.микроконтроллер с аппаратным последовательным интерфейсом, то
можно легко сделать из него параллельный порт, принимая данные (команды) от PC по виртуальному
COM-порту на USB, и отсылая по нему же назад данные с PIN-ов.

А второй трюк, собственно из-за него я и купил этот бестолковый адаптер - Gembird USB to Bitronics
Converter
. Я предполагал, что он не сможет работать побитно, но читал статью, где пишут, что можно
его использовать для управления чем-либо родными командами вывода на печать Венды, если соблюдать
протокол, характерный для обмена LPT и принтера CENTRONICS.
А для этого, как было написано в статье, достаточно подавать инвертированный сигнал STROBE на
собственный же вход BUSY.
iLavr
Tronix
Doomed
Posts: 662
Joined: 18 Nov 2013 02:38
Location: Москва

Post by Tronix »

Итого, вместо 9 обращений по USB я ж могу слать только данные (2 обращения), а остальными ногами дергать в самом контроллере, в зависимости от того - первый это байт или второй:

Code: Select all

bc1 = 1 ; bdir = 1 ; res = 1        ; Reset
bc1 = 1 ; bdir = 1 ; res = 0        ; Reset
bc1 = 1 ; bdir = 1 ; res = 1        ; Reset

bc1 = 0 ; bdir = 0 ; res = 1      ;YM inactive    ;1 IO USB
Data = 12                             ; данные        ; 2 IO USB
bc1 = 1 ; bdir = 1 ; res = 1      ; писать адрес ;3 IO USB
Data = 12                             ; данные         ;4 IO USB
bc1 = 0 ; bdir = 0 ; res = 1      ; YM inactive   ;5 IO USB
Data = 0                               ; данные        ;6 IO USB
bc1 = 0 ; bdir = 1 ; res = 1      ; писать данные ;7 IO USB
Data = 0                               ; данные        ; 8 IO USB
bc1 = 0 ; bdir = 0 ; res = 1      ; YM inactive  ; 9 IO USB


bc1 = 0 ; bdir = 0 ; res = 1
Data = 11
bc1 = 1 ; bdir = 1 ; res = 1
Data = 11
bc1 = 0 ; bdir = 0 ; res = 1
Data = 0
bc1 = 0 ; bdir = 1 ; res = 1
Data = 0
bc1 = 0 ; bdir = 0 ; res = 1

То есть в обертке inpout.dll я должен контроллеру выдавать только данные (порт 0x378), причем пропускать каждый второй байт. В самом контроллере я должен использовать флаг, показывающий - первый байт пришел или второй. Если первый - то сам контроллер должен выставить bc1 = 1, bdir = 1. Если второй, то bc1 = 0, bdir1 = 1. И так по-кругу.

Вчера уже поздно вечером попробовал - что-то не взлетает. Какие-то шумы и хрипы. Не очень хорошо в даташите показаны тайминги цикла записи и цикла записи адреса. Пытался сделать так как и было раньше:

установил bc1=0, bdir=0 (YM inactive)
выдал байт данных на ноги D0-D7
если первый байт то bc1=1, bdir=1
иначе bc1=0, bdir = 1
подождал около ~1500 нс
установил bc1=0, bdir=0 (YM inactive)

Не работает.
То есть процедура вывода байта в ПИКе такая:

Code: Select all

DIO_WriteByte:

    bcf     PORTA,3                 ; bc1 = 0
    bcf     PORTA,4                 ; bdir = 0

    movlw   0x10                    ; delay 0.00005 sec (24MHz)
    movwf   TMP
wait2:
    decfsz  TMP
    goto    wait2

    ;Put value in RB3-RB7
    movlw   B'00000111'
    andwf   PORTB,W
    movwf   TMP
    movlw   B'11111000'
    andwf   RXDATA_BUFFER+4,W       ;wIndex Lo
    iorwf   TMP,W
    movwf   PORTB

    ;Put the last bits values in RA0-RA2
    movlw   B'11111000'
    andwf   PORTA,W
    movwf   TMP
    movlw   B'00000111'
    andwf   RXDATA_BUFFER+4,W       ;wIndex Lo
    iorwf   TMP,W
    movwf   PORTA
    
    btfsc   ODDEVEN,0               ; this is first byte in queque?
    goto    second_byte             ; no, goto second byte

                                    ; yes - thi is firs byte
    bsf     ODDEVEN,0               ; set zero bit in ODDEVEN flag

    bsf     PORTA,3                 ;bc1 = 1
    bsf     PORTA,4                 ;bdir = 1

    goto    ctrl_done               ; controll done

second_byte:
    bcf     ODDEVEN,0               ; clear zero bit in ODDEVEN flag
    bcf     PORTA,3                 ; bc1 = 0
    bsf     PORTA,4                 ; bdir = 1
ctrl_done:

    movlw   0x10                    ; delay 0.00005 sec (24MHz)
    movwf   TMP
wait:
    decfsz  TMP
    goto    wait

    bcf     PORTA,3                 ; bc1 = 0
    bcf     PORTA,4                 ; bdir = 0
    return
В обертке inpout32.dll такое:

Code: Select all

		switch (port)
		{
		case 0x378:
			if (skip_data == 0) 
				writeByte(Value); 
			skip_data = ~skip_data;
			break;
Tronix
Doomed
Posts: 662
Joined: 18 Nov 2013 02:38
Location: Москва

Post by Tronix »

Оказываеццо, некошерно менять значения в порту командами BCF/BSF. Есть где-то вроде аппноут от микрочипа, но здесь все детально и так написано: http://www.piclist.com/techref/readmodwrite.htm . Иногда помогает задержка между BCF, но тоже говнокод и так типа нехорошо делать. Что ж, попробуем через read modify write.
User avatar
Lavr
Supreme God
Posts: 16680
Joined: 21 Oct 2009 08:08
Location: Россия

Post by Lavr »

Tronix wrote:Оказываеццо, некошерно менять значения в порту командами BCF/BSF.
Некошерно, но в оригинале прошивки так было и нормально работало себе?
iLavr
Tronix
Doomed
Posts: 662
Joined: 18 Nov 2013 02:38
Location: Москва

Post by Tronix »

Lavr wrote:
Tronix wrote:Оказываеццо, некошерно менять значения в порту командами BCF/BSF.
Некошерно, но в оригинале прошивки так было и нормально работало себе?
В оригинале прошивки такого не было. Там как раз все культурно, через read modify write. Это я уже пытался bc1 bdir сам контролировать.
Переписал по нормальному, все равно не работает.
Tronix
Doomed
Posts: 662
Joined: 18 Nov 2013 02:38
Location: Москва

Post by Tronix »

Ну ессно баг был в том, что я переменную в памяти PIC затирал потом в другом месте (не правильно описал). Поправил, заработало как и планировалось - по USB передаются только байты, а контроллер сам дергает BC1 и BDIR в зависимости от того - четный это байт или не четный. Все равно медленно, хотя с первым разом не сравнить:

https://soundcloud.com/tronix286/jok...chby-surgeon-1

Это уже видимо совсем предел. Остается только еще попробовать буферизировать паттерн (28 байт) в самом ПИКе, а потом его проигрывать параллельно с приемом новой порции данных (двойная буферизация), но что-то мне говорит о том, что это будет все равно медленно.

Все-таки наверное придется юзать другой PIC, с хардварным USB на борту. Как раз спаял недавно б/у PIC18F2550 с какой-то платы...
Tronix
Doomed
Posts: 662
Joined: 18 Nov 2013 02:38
Location: Москва

Post by Tronix »

Окончательный код записи байта в YM:

Code: Select all

DIO_WriteByte:

    ;Put value in RB3-RB7
    movlw   B'00000111'
    andwf   PORTB,W
    movwf   TMP
    movlw   B'11111000'
    andwf   RXDATA_BUFFER+4,W       ;wIndex Lo
    iorwf   TMP,W
    movwf   PORTB

    ;Put the last bits values in RA0-RA2
    movlw   B'11111000'
    andwf   PORTA,W
    movwf   TMP
    movlw   B'00000111'
    andwf   RXDATA_BUFFER+4,W       ;wIndex Lo
    iorwf   TMP,W
    
    iorlw   B'00011000'             ;set bc1=1, bdir=1
    btfsc   ODDEVEN,0               ;skip next intruction if first byte
    andlw   B'11110111'             ;set bc1=0, bdir=1 if second byte
    movwf   PORTA

    andlw   B'11100111'             ; set bc1=0, bdir=0 (inactive)
    movwf   PORTA
    movlw   B'00000001'             ; toggle ODDEVEN flag
    xorwf   ODDEVEN,F

    return
Tronix
Doomed
Posts: 662
Joined: 18 Nov 2013 02:38
Location: Москва

Post by Tronix »

Тут провел небольшой тестик - в цикле писал 1000 байт и засек время выполнения: 1.085690 секунд. То есть скорость ~ 1000 байт/сек.....

Поснифал USB-трафик. Если я все правильно понял, то посылка от хоста контроллеру занимает 36 байт, контроллер отвечает хосту 28 байт. Итого на посылку 1 байта приходится физически 36+28=64 байта. То есть фактически скорость ~64Кбайт в секунду. Если я правильно понимаю, то 1,5Mbit/s USB 1.1 это ~192Kбайт в сек, то есть в пропускную способность не уперлись.
Tronix
Doomed
Posts: 662
Joined: 18 Nov 2013 02:38
Location: Москва

Post by Tronix »

Короче, пришлось таки вкурить немного манов на тему USB протокола, как я ни сопротивлялся -) Поснифал USB-трафик, разобрался. Хотел сначала в след за контрол-пакетом слать дата пакет 8 байт данных, а потом просто запилил в ubr-пакет OUT передачу сразу 3 байт, вместо 1, как было раньше. Тем самым скорость передачи сразу возросла в три раза. Короче, заработало как и хотелось

https://soundcloud.com/tronix286/joke-o ... geon-final
Tronix
Doomed
Posts: 662
Joined: 18 Nov 2013 02:38
Location: Москва

Post by Tronix »

jdigreze
God
Posts: 1388
Joined: 02 Jan 2006 02:28
Location: Abakan

Post by jdigreze »

Ну, это буквально - ПОБЕДА! ;)