Телесистемы
 Разработка, производство и продажа радиоэлектронной аппаратуры
На главную   | Карта сайта | Пишите нам | В избранное
Требуется программист в Зеленограде
- обработка данных с датчиков; ColdFire; 40 тыс.
e-mail:jobsmp@pochta.ru

Телесистемы | Электроника | Конференция «Микроконтроллеры и их применение»

Ну я ACK генерил, если интересно, вот моя реализация PS/2:

Отправлено Леонид Иванович 05 октября 2007 г. 21:59
В ответ на: PS/2 читаю вижу в некоторых мануалах есть ACK на команду, а в других нет, и в осциллографе нет, кому верить ?) отправлено <font color=gray>ничего не знаю</font> 05 октября 2007 г. 18:39


//----------------------------------------------------------------------------

#include
#include

//----------------------------- Constants: -----------------------------------

//PS/2 port pins:
#define CLK (1 << PB0) //PS/2 clock line
#define DATA (1 << PB1) //PS/2 data line

//pin control macros:
#define PIN_CLK (PINB & CLK) //read clock line
#define PORT_CLK_Z (DDRB &= ~CLK) //set clock line to z-state
#define PORT_CLK_0 (DDRB |= CLK) //set clock line to low state
#define PIN_DATA (PINB & DATA) //read data line
#define PORT_DATA_Z (DDRB &= ~DATA) //set data line to z-state
#define PORT_DATA_0 (DDRB |= DATA) //set data line to low state

#define TPS2 20.0 //PS/2 port timebase (1/4 period), uS
#define TX_DELAY 160.0 //inter-symbol delay

//Clock line states:
enum { CS_LOW,
CS_RISE,
CS_HIGH,
CS_FALL };

//----------------------------- Variables: -----------------------------------

static char PortState; //PS/2 port state
static char ClockState; //clock line state
static char ByteIndex; //byte shift index
static char Tx_Byte; //data byte to TX
static bool Tx_Parity; //parity bit to TX
static bool Tx_Complete; //TX complete flag
static char Rx_Byte; //received data byte
static bool Rx_Complete; //RX complete flag
static bool fTick; //new tick flag

//------------------------- Function prototypes: -----------------------------

void Ps2io_Tx(char byte); //begin transmit byte to host
bool GetParity(char d); //calculate odd parity bit
#pragma vector = TIMER1_COMPA_vect
__interrupt void Ps2_Timer(void); //timer interrupt

//------------------------ PS/2 port module init: ----------------------------

void Ps2io_Init(void)
{
DDRB = 0; //all pins are inputs
PORTB = ~(CLK | DATA); //turn on pullups for unused pins

TCCR1A = 0; //OC disable, PWM disable
TCCR1B = (1 << WGM12) | (1 << CS10); //CTC, CK/1
OCR1AH = HI((int)((FCLK * TPS2) + 0.5)); //compare register load
OCR1AL = LO((int)((FCLK * TPS2) + 0.5));
TIFR = (1 << OCIE1A); //clear pending interrupts
TIMSK = (1 << OCIE1A); //timer interrupts enable

PortState = PS_IDLE; //PS/2 port state
Tx_Complete = 1; //set TX complete flag (no pending data)
Rx_Complete = 0; //clear RX complete flag (no incoming data)
}

//------------------------- Get PS/2 port state: -----------------------------

char Ps2io_State(void)
{
return(PortState);
}

//--------------------- Begin transmit byte to host: -------------------------

__monitor void Ps2io_Tx(char byte)
{
Tx_Byte = byte;
Tx_Parity = GetParity(Tx_Byte); //get parity bit
ClockState = CS_RISE; //turn on the clock
ByteIndex = 0; //reset the byte index for transmit
Tx_Complete = 0; //clear TX complete flag
PortState = PS_TRANSMIT; //begin transmit
}

//------------------------- Check TX complete: -------------------------------

bool Ps2io_Transmitted(void)
{
return(Tx_Complete);
}

//------------------------- Check RX complete: -------------------------------

bool Ps2io_Received(void)
{
return(Rx_Complete);
}

//------------------------- Get receivet byte: -------------------------------

char Ps2io_Rx(void)
{
Rx_Complete = 0; //clear RX complete flag
return(Rx_Byte);
}

//------------------------- System tick check: -------------------------------

__monitor bool Ps2io_GetTick(void)
{
if(!fTick) return(0);
fTick = 0;
return(1);
}

//-------------------------- Timer interrupt: --------------------------------

#pragma vector = TIMER1_COMPA_vect
__interrupt void Ps2_Timer(void)
{
static char Tick_Timer = 0; //tick timer
static char Tx_Timer = 0; //TX timer

//Tick timer:
if(++Tick_Timer == (TICK / TPS2))
{
Tick_Timer = 0;
fTick = 1;
}
//TX timer:
if(Tx_Timer) Tx_Timer--;

switch(PortState)
{
//Port state ---------> IDLE.
case PS_IDLE:
if(!PIN_CLK)
{
PortState = PS_INHIBIT; //clock pulled low by host
}
break;

//Port state ---------> TRANSMIT.
case PS_TRANSMIT:
if(Tx_Timer) break; //wait iner-symbol delay
switch(ClockState)
{
case CS_RISE: //CLK = 0 -> 1
PORT_CLK_Z;
ClockState = CS_HIGH;
if(ByteIndex == 11)
{
Tx_Complete = 1; //set TX complete flag
Tx_Timer = TX_DELAY / TPS2; //TX timer load
PortState = PS_IDLE; //transmit finished
}
break;

case CS_HIGH: //CLK = 1
if(!PIN_CLK && ByteIndex < 10)
{
PORT_DATA_Z; //release the data line
PortState = PS_INHIBIT; //clock pulled low by host
break;
}
switch(ByteIndex)
{
case 0:
PORT_DATA_0; //tx start bit
break;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
(Tx_Byte & 0x01)? PORT_DATA_Z : PORT_DATA_0; //tx data bits
Tx_Byte = Tx_Byte >> 1;
break;
case 9:
(Tx_Parity)? PORT_DATA_Z : PORT_DATA_0; //tx parity bit
break;
case 10:
PORT_DATA_Z; //tx stop bit
break;
}
ByteIndex++; //next bit
ClockState = CS_FALL;
break;

case CS_FALL: //CLK = 1 -> 0
PORT_CLK_0;
ClockState = CS_LOW;
break;

case CS_LOW: //CLK = 0
ClockState = CS_RISE;
break;
}
break;

//Port state ---------> INHIBIT.
case PS_INHIBIT:
if(PIN_CLK) //wait for release the CLK
{
PortState = PS_REQUEST;
}
break;

//Port state ---------> WAIT FOR REQUEST.
case PS_REQUEST:
if(!PIN_DATA) //check the data line
{
ByteIndex = 0;
PortState = PS_RECEIVE; //begin receive data from the host
ClockState = CS_FALL;
}
else
{
PortState = PS_IDLE;
}
break;

//Port state ---------> RECEIVE.
case PS_RECEIVE:
switch (ClockState)
{
case CS_RISE: //CLK = 0 -> 1
PORT_CLK_Z;
if(ByteIndex < 8)
{
if(PIN_DATA) Rx_Byte = Rx_Byte | 0x01;
Rx_Byte = Rx_Byte << 1;
}
ByteIndex++;
ClockState = CS_HIGH;
break;

case CS_HIGH: //CLK = 1
if(!PIN_CLK && ByteIndex < 10)
{
PortState = PS_INHIBIT;
break;
}
switch (ByteIndex)
{
case 10:
PORT_DATA_0; //send ACK
break;
case 11:
PORT_DATA_Z; //release the data line
Rx_Complete = 1; //set RX complete flag
Tx_Timer = TX_DELAY / TPS2; //TX timer load
PortState = PS_IDLE; //receive finished
break;
}
ClockState = CS_FALL;
break;

case CS_FALL: //CLK = 1 -> 0
PORT_CLK_0;
ClockState = CS_LOW;
break;

case CS_LOW: //CLK = 0
ClockState = CS_RISE;
break;
}
break;
}
}

//----------------------- Calculate odd parity bit: --------------------------

bool GetParity(char d)
{
d ^= (d >> 4);
d ^= (d >> 2);
d ^= (d >> 1);
d &= 0x01;
return(!d);
}

//----------------------------------------------------------------------------



Составить ответ | Вернуться на конференцию

Ответы


Отправка ответа
Имя*: 
Пароль: 
E-mail: 
Тема*:

Сообщение:

Ссылка на URL: 
URL изображения: 

если вы незарегистрированный на форуме пользователь, то
для успешного добавления сообщения заполните поле, как указано ниже:
скольким Омам равен эквивалент двух резисторов по 10 Ом, соединённых параллельно?:

Перейти к списку ответов | Конференция | Раздел "Электроника" | Главная страница | Карта сайта

Rambler's Top100 Рейтинг@Mail.ru
 
Web telesys.ru