Кто-нибудь использовал subj? Есть проблема. Пытаюсь заставить работать
стандартный пример для BF561 Video_INOUT. Hа плате имеются видеодекодер
ADV7183A (с автоматическим определением формата видеосигнала) и видеокодер
ADV7179 (после сброса работает в NTSC). В программе по умолчанию задан
Entire Field Mode с разрешением 858x525 (NTSC). Проверить работоспособность
этой программы с NTSC сигналом нет возможности, так как нет NTSC. :) Поэтому
меняю разрешение на 864x625 (PAL, стандарт ITU-R 656). Hа картинке на мониторе
явная проблема с кадровой синхронизацией, смещена, видны черные горизонтальные
полосы. Со строчной все вроде в порядке. Смотрю в Image Viewer дамп памяти,
куда сохраняются кадры. Вместо двух полукадров вижу один целый посередине и
где-то две половинки вверху и внизу. После долгих размышлений и копания в коде
наткнулся на такую вещь. Во время инициализации, после сброса декодера ADV7183A
выдерживается определенная пауза (простой цикл nop на некоторое магическое
число). Якобы для того чтобы декодер успел синхронизироваться с аналоговым
сигналом. Увеличиваю этот цикл в несколько раз. Включаю. Hа мониторе
практически то же самое. В дампе памяти - четко два полукадра. Видна черная
полоска и строчной, и кадровой. Однако, в начале дампа кадра сразу же идет
последовательность 0x80, 0x10... без заголовка 0xFF 0x00 0x00 XY. Изменяя
паузу, получаю различное смещение полукадров по вертикали. Извечный вопрос -
что делать? :) Проблема явно в декодере. Он вообще не трогается, находится
в дефолтном состоянии после сброса. Однако имеется возможность его
программировать через I2C. В видеокодере я устанавливал PAL режим и выводил
внутреннюю тестовую таблицу color bars (тоже через I2C). Так что с ним все OK.
Кстати, вопрос по I2C. Hа скорую руку пришлось самому его реализовывать
программно (так как в BF561 его нет). Может где уже есть его реализация для
BF561? В инете нашел ссылку на www.blackfin.org. Hо этого сайта уже нет, читал
только форумы в кэше гугла.
--
Victor
Fri, 14 Jul 2006 22:51:14, Victor Bazhenov wrote:
Проблема решена.
--
Victor
VB> Пpоблема pешена.
а что было?
Майкл
VB> Кстати, вопрос по I2C. Hа скорую руку пришлось самому его реализовывать
VB> программно
Программная реализация неблокирующего I2C мастера. Умеет писать и читать
блоки данных. Отрабатывает вейтстейты.
Вызывается из таймерного прерывания. Cкорость прерывания = 4 x скорость I2C.
Enjoy.
//----------- I2C.H ---------------------------
#ifndef __I2C_H_INCLUDED
#define __I2C_H_INCLUDED
#include "main_defs.h"
#include "types.h"
// Platform dependent definitions
#define SCL_MASK 0x01
#define SDA_MASK 0x02
#define SET_SCL do { DDRB &= ~SCL_MASK; PORTB |= SCL_MASK; } while(0)
#define CLR_SCL do { DDRB |= SCL_MASK; PORTB &= ~SCL_MASK; } while(0)
#define GET_SCL ((PINB&SCL_MASK) ? 1:0)
#define SET_SDA do { DDRB &= ~SDA_MASK; PORTB |= SDA_MASK; } while(0)
#define CLR_SDA do { DDRB |= SDA_MASK; PORTB &= ~SDA_MASK; } while(0)
#define GET_SDA ((PINB&SDA_MASK) ? 1:0)
// I2C system return codes
#define I2C_BUSY 0
#define I2C_READY 1
// The low level I2C bus states
typedef enum {
I2C_BUS_STATE_IDLE,
I2C_BUS_STATE_START_0,
I2C_BUS_STATE_START_1,
I2C_BUS_STATE_TX_0,
I2C_BUS_STATE_TX_1,
I2C_BUS_STATE_TX_3,
I2C_BUS_STATE_TX_4,
I2C_BUS_STATE_TX_5,
I2C_BUS_STATE_TX_6,
I2C_BUS_STATE_TX_7,
I2C_BUS_STATE_STOP_1,
I2C_BUS_STATE_STOP_2,
I2C_BUS_STATE_STOP_3,
I2C_BUS_STATE_STOP_4,
I2C_BUS_STATE_RX_1,
I2C_BUS_STATE_RX_2,
I2C_BUS_STATE_RX_3,
I2C_BUS_STATE_RX_4,
I2C_BUS_STATE_RX_5,
I2C_BUS_STATE_RX_6
} I2C_BUS_STATE;
typedef struct {
I2C_BUS_STATE bus_state;
u8 status;
u8 address; // Address for communication + R/W bit
u8 *buffer;
u8 length; // length of the data
u8 byte_cntr; // index for data
u8 delay_cntr;
u8 waitstate_state;
u8 byte;
u8 byte_bit_cntr;
} I2C_STRUCT;
void I2C_Init(void);
u8 I2C_Status(void);
u8 I2C_Action(u8 addr, u8 *data, u8 length);
void I2C_BitBanging(void); // To be called from the interrupt with 4x I2C
baud rate
void I2C_WaitStateCheck(void); // Aux. function
#endif
//----------- I2C.C ----------------------------
/* Interrupt driven I2C master */
/* (c) Abvolt. Ltd */
/* VLV 2005 */
#include "i2c.h"
static volatile I2C_STRUCT i2c;
void I2C_Init(void)
{
SET_SDA;
SET_SCL;
i2c.bus_state = I2C_BUS_STATE_IDLE;
i2c.status = I2C_READY;
i2c.address = 0;
i2c.buffer = (u8*)0;
i2c.length = 0;
i2c.byte_cntr = 0;
i2c.delay_cntr = 0;
i2c.waitstate_state = 0;
i2c.byte = 0;
i2c.byte_bit_cntr = 8;
}
//-----------------------
u8 I2C_Status(void)
{
return i2c.status;
};
//---------- Transmit/Receive Block ---------------------------
// The address is 8 bits, the LSBit ==1 for read, ==0 for write
//
u8 I2C_Action(u8 addr, u8 *data, u8 length)
{
u8 ret_val;
ret_val = i2c.status;
if(ret_val == I2C_READY)
{
i2c.buffer = data;
i2c.length = length;
i2c.address = addr;
i2c.byte_cntr = 0;
i2c.byte_bit_cntr = 8;
i2c.status = I2C_BUSY;
i2c.bus_state = I2C_BUS_STATE_START_0;
}
return ret_val;
}
//--------- Aux function used in the I2C state machine ------
void I2C_WaitStateCheck(void)
{
SET_SCL; // SCL high
i2c.delay_cntr = 1; // Wait 1/2 bit
i2c.waitstate_state = 1; // Check for SCL
}
//---------------------------------------------
// This function should be called from the interrupt
// with the rate of 4xI2C_BITRATE
void I2C_BitBanging(void)
{
// If there is a delay, do nothing
// If waitstate, process waitstate
// Else proceed to the state machine
if(i2c.delay_cntr)
{
i2c.delay_cntr--;
}
else if((i2c.waitstate_state == 1)&&(!GET_SCL))
{
i2c.waitstate_state = 2;
i2c.delay_cntr = 1;
}
else if(i2c.waitstate_state == 2)
{
if(GET_SCL) i2c.waitstate_state = 0;
i2c.delay_cntr = 1;
}
else
{
i2c.waitstate_state = 0;
switch(i2c.bus_state)
{
//----- I2C in idle = do nothing ------
case I2C_BUS_STATE_IDLE:
default:
break;
//---------- Start sequence --------
case I2C_BUS_STATE_START_0:
I2C_WaitStateCheck();
i2c.bus_state = I2C_BUS_STATE_START_1;
break;
case I2C_BUS_STATE_START_1:
CLR_SDA;
i2c.delay_cntr = 1;
i2c.bus_state = I2C_BUS_STATE_TX_0;
i2c.byte = i2c.address;
i2c.byte_bit_cntr = 8;
i2c.byte_cntr = 0;
break;
//------------- Transmit byte --------
case I2C_BUS_STATE_TX_0:
CLR_SCL;
i2c.bus_state = I2C_BUS_STATE_TX_1;
break;
case I2C_BUS_STATE_TX_1:
if(i2c.byte&0x80) SET_SDA;
else CLR_SDA;
i2c.byte <<= 1;
i2c.bus_state = I2C_BUS_STATE_TX_3;
break;
case I2C_BUS_STATE_TX_3:
I2C_WaitStateCheck();
i2c.byte_bit_cntr--;
if(!i2c.byte_bit_cntr)
{
i2c.byte_bit_cntr = 8;
i2c.bus_state = I2C_BUS_STATE_TX_4; // Read ACK
}
else // Transmit next bit in the byte
{
i2c.bus_state = I2C_BUS_STATE_TX_0;
}
break;
// Read ACK from the slave
case I2C_BUS_STATE_TX_4:
CLR_SCL;
i2c.bus_state = I2C_BUS_STATE_TX_5;
break;
case I2C_BUS_STATE_TX_5:
SET_SDA; // Release SDA only when SCL is low
i2c.bus_state = I2C_BUS_STATE_TX_6;
break;
case I2C_BUS_STATE_TX_6:
I2C_WaitStateCheck();
i2c.bus_state = I2C_BUS_STATE_TX_7;
break;
case I2C_BUS_STATE_TX_7:
// Here we can read ACK
// ask = GET_SDA;
CLR_SCL;
if(i2c.address&0x01) // To read sequence
{
if(i2c.length)
{
i2c.delay_cntr = 1;
i2c.bus_state = I2C_BUS_STATE_RX_1;
}
else
{
i2c.bus_state = I2C_BUS_STATE_STOP_1;
}
}
else // Write sequence
{
if(i2c.byte_cntr >= i2c.length) // End of data
{
i2c.bus_state = I2C_BUS_STATE_STOP_1;
}
else // To next byte for transmission
{
i2c.byte = i2c.buffer[i2c.byte_cntr];
i2c.byte_cntr++;
i2c.bus_state = I2C_BUS_STATE_TX_1;
}
}
break;
//---------- I2C STOP processing -------------
case I2C_BUS_STATE_STOP_1:
CLR_SDA;
i2c.bus_state = I2C_BUS_STATE_STOP_2;
break;
case I2C_BUS_STATE_STOP_2:
I2C_WaitStateCheck();
i2c.bus_state = I2C_BUS_STATE_STOP_3;
break;
case I2C_BUS_STATE_STOP_3:
SET_SDA;
i2c.delay_cntr = 7;
i2c.bus_state = I2C_BUS_STATE_STOP_4;
break;
case I2C_BUS_STATE_STOP_4: // Stop is complete
i2c.status = I2C_READY;
i2c.bus_state = I2C_BUS_STATE_IDLE;
break;
//--------- I2C master read processing --------
case I2C_BUS_STATE_RX_1:
I2C_WaitStateCheck();
i2c.bus_state = I2C_BUS_STATE_RX_2;
break;
case I2C_BUS_STATE_RX_2:
i2c.byte = ((i2c.byte<<1) | GET_SDA)&0xFF;
CLR_SCL;
i2c.byte_bit_cntr--;
if(!i2c.byte_bit_cntr)
{
i2c.byte_bit_cntr = 8;
i2c.buffer[i2c.byte_cntr] = i2c.byte;
i2c.byte_cntr++;
i2c.bus_state = I2C_BUS_STATE_RX_3;
}
else
{
i2c.delay_cntr = 1;
i2c.bus_state = I2C_BUS_STATE_RX_1;
}
break;
// Send ACK/NAK when a byte is received
case I2C_BUS_STATE_RX_3:
if(i2c.byte_cntr >= i2c.length) // last byte -> NAK
{
SET_SDA;
}
else // ACK
{
CLR_SDA;
}
i2c.bus_state = I2C_BUS_STATE_RX_4;
break;
case I2C_BUS_STATE_RX_4:
I2C_WaitStateCheck();
i2c.bus_state = I2C_BUS_STATE_RX_5;
break;
case I2C_BUS_STATE_RX_5:
CLR_SCL;
i2c.bus_state = I2C_BUS_STATE_RX_6;
break;
case I2C_BUS_STATE_RX_6:
if(i2c.byte_cntr >= i2c.length) // last byte
{
CLR_SDA;
i2c.bus_state = I2C_BUS_STATE_STOP_2;
}
else // Next byte
{
SET_SDA;
i2c.bus_state = I2C_BUS_STATE_RX_1;
}
break;
}
}
}
//=========== <END>==============
"Любите книги - в них видно фиги" (c)
Wed, 19 Jul 2006 19:13:32, Michael Mamaev wrote:
VB>> Пpоблема pешена.
MM> а что было?
Hу как и предполагал - перепрограммирование декодера и кодера на PAL помогло.
А вообще тут кто-нибудь использует Blackfin вообще и BF561 в частности?
--
Victor
VB> А вообще тyт кто-нибyдь использyет Blackfin вообще и BF561 в
VB> частности?
Пока только за доскy немного подеpжался, а свою платy еще только pазводим.
Майкл