Выложил сорцы в сообщение с картинкой.
Вид для печати
Выложил сорцы в сообщение с картинкой.
Вощем как я и предполагал, D1 - это /BDIR, D2 - BC1 и D3 - /RESET. Звук пошел, но с такими тормозами, что ппц. Не успевает видать софтварный USB... Попробую еще поковыряться конечно, но видимо все-таки придется юзать контроллер с аппаратным USB.
Вот такой лол вышел:
https://soundcloud.com/tronix286/jok...bachby-surgeon
Данные пишутся пакетами по 28 байт раз в 20мс (50гц частота)
Итого, вместо 9 обращений по USB я ж могу слать только данные (2 обращения), а остальными ногами дергать в самом контроллере, в зависимости от того - первый это байт или второй:
То есть в обертке inpout.dll я должен контроллеру выдавать только данные (порт 0x378), причем пропускать каждый второй байт. В самом контроллере я должен использовать флаг, показывающий - первый байт пришел или второй. Если первый - то сам контроллер должен выставить bc1 = 1, bdir = 1. Если второй, то bc1 = 0, bdir1 = 1. И так по-кругу.Код: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
Вчера уже поздно вечером попробовал - что-то не взлетает. Какие-то шумы и хрипы. Не очень хорошо в даташите показаны тайминги цикла записи и цикла записи адреса. Пытался сделать так как и было раньше:
установил bc1=0, bdir=0 (YM inactive)
выдал байт данных на ноги D0-D7
если первый байт то bc1=1, bdir=1
иначе bc1=0, bdir = 1
подождал около ~1500 нс
установил bc1=0, bdir=0 (YM inactive)
Не работает (
---------- Post added at 12:43 ---------- Previous post was at 12:19 ----------
То есть процедура вывода байта в ПИКе такая:
В обертке inpout32.dll такое:Код: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
PHP код:switch (port)
{
case 0x378:
if (skip_data == 0)
writeByte(Value);
skip_data = ~skip_data;
break;
Оказываецо, некошерно менять значения в порту командами BCF/BSF. Есть где-то вроде аппноут от микрочипа, но здесь все детально и так написано: http://www.piclist.com/techref/readmodwrite.htm . Иногда помогает задержка из NOPов между BCF, но тоже быдлокод и так типа нехорошо делать.
Переписал вроде как правильно, через чтение - модификацию - запись. Например установка bc1=1 bdir=1 теперь происходит так:
Все равно, какие-то хрипы и вообще не то все.... Смотрю инет на эту тему - вроде просто все у всех, вот тут чувак на AVR делает так:Код:;bsf PORTA,3 ;bc1 = 1
;bsf PORTA,4 ;bdir = 1
movlw B'11100111'
andwf PORTA,W
movwf TMP
movlw B'00011000'
iorwf TMP,W
movwf PORTA
Ну и у меня так же, в принципе.... Чуствую какая-то мелкая ошибка где-то...PHP код:void send_ay(int reg, int data){
PORTC = 0x00; //send 'inactive', logical 0 to BDIR/BC1
PORTD = reg; //put register number on data port
PORTC = 0x03; //send 1 to BDIR/BC1 to latch register address
PORTC = 0x00; //inactive
PORTD = data; //data to send to previously selected register
PORTC = 0x01; //send 1 to BDIR, 0 to BC1 to latch data to register
}
Мож сбрасывать YM надо все-таки, а то хз что у него там в памяти сидит... Прикручу сброс. Потом в пошаговом режиме еще потестю, тестором сигналы чтоб мерять.
Ну ессно баг был в том, что я переменную в памяти PIC затирал потом в другом месте (не правильно описал). Поправил, заработало как и планировалось - по USB передаются только байты, а контроллер сам дергает BC1 и BDIR в зависимости от того - четный это байт или не четный. Все равно медленно, хотя с первым разом не сравнить:
https://soundcloud.com/tronix286/jok...chby-surgeon-1
Щаз еще попробую оптимизировать код в пике, но это уже почти предел я думаю.. Но - "почти" -)
Как вариант - если применить внешнее тактирование (напр., от генератора типа тех, что стояли на старых материнках), то старые PIC-и работают и на гораздо более высоких частотах.
У меня , напр., PIC16F690 нормально переваривает 32MHz, потребление при этом - ок. 15мА, ессно, ничего не греется.