Вобщем в некоторых схемах делают просто - подтягивают через через 27k резистор линию к +3.3в (порой даже без диода) и сразу на ногу микроконтроллера.
Работать скорее всего будет, но как то глубокого соответствия стандарту и защищенности от разных напастий судьбы не ощущается...
Покапавшись в разных аппликейшн нотах на тему CEC и описанию, получилось такое:
Вложение:
cec_hwd.PNG [11.14 KiB]
Скачиваний: 1392
Диод тут или быстровосстанавливающийся с малым паденим напряжения, или лучше шотки с не сильно большим обратным током.
С прерываниями на атмеловом арме по изменению состояни ноги чтото я или не разобрался, или патроны не той системы (чтото типа дребезга контактов), пока выкинул.
Для sam7s256 атмеловского.
чего достиг - выводятся на консоль пакеты пакеты опроса присутствия девайнос на шине и все -))
тошибовский 46 дюймовый телек такие раз в 3-4 минуты рассылает, ловятся.
#include "board.h"
#include "aic.h"
#include "pio.h"
#include <pit.h>
#include <utility/trace.h>
/* CEC Start Bit Timing Defintions, in us (10-6 s) */
/* Recieve Start */
#define Sbit_Min_LD 35 // Start Bit Minimum Low duration
#define Sbit_Max_LD 39 // Start Bit Maximum Low duration
#define Sbit_Min_TD 43 // Start Bit Minimum Total duration
#define Sbit_Max_TD 47 // Start Bit Maximum Total duration
/* Transmit Start */
#define Sbit_Nom_LD 37 // Start Bit Nominal Low duration
#define Sbit_Nom_HD 8 // Start Bit Nominal High Duration
/* Recieve Data */
#define Dbit_Min_TD 20 // Data Bit Minimum Total Duration
#define Dbit_Max_TD 28 // Data Bit Maximum Total Duration
#define Dbit_Sample 11 // Data Bit Sample time
/* Transmit Data */
#define Dbit_High_LD 6 // Data Bit Nominal Low duration
#define Dbit_High_HD 18 // Data Bit Nominal High Duration
#define Dbit_Low_LD 15 // Data Bit Nominal Low duration
#define Dbit_Low_HD 9 // Data Bit Nominal High Duration
#define Ack_HD 13 // Set High duration after ACK
#define Ack_sample 5 // The acknowledge is sampled after the low duration is transmitted.
/// PIT period value in µseconds.
#define PIT_PERIOD 100
/// Global timestamp in milliseconds since start of application.
volatile unsigned int timestamp = 0;
volatile int waiting_edge; // 1 - pos, 0 - neg
volatile int lasttimestamp;
#define IRQDELAY 2
//----------
// Local functions
//----------
//----------
/// Handler for PIT interrupt. Increments the timestamp counter.
//----------
void ISR_Pit(void)
{
unsigned int status;
// Read the PIT status register
status = PIT_GetStatus() & AT91C_PITC_PITS;
if (status != 0)
{
// Read the PIVR to acknowledge interrupt and get number of ticks
timestamp += (PIT_GetPIVR() >> 20);
}
}
//----------
/// Configure the periodic interval timer to generate an interrupt every
/// millisecond.
//----------
void ConfigurePit(void)
{
// Initialize the PIT to the desired frequency
PIT_Init(PIT_PERIOD, BOARD_MCK / 1000000);
// Configure interrupt on PIT
AIC_DisableIT(AT91C_ID_SYS);
AIC_ConfigureIT(AT91C_ID_SYS, AT91C_AIC_PRIOR_LOWEST, ISR_Pit);
AIC_EnableIT(AT91C_ID_SYS);
PIT_EnableIT();
// Enable the pit
PIT_Enable();
}
Pin output = {AT91C_PIO_PA31, AT91C_BASE_PIOA, AT91C_ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
enum _frame_state { B_START_L=0, B_START_H, B_1_L, B_1_H, B_2_L, B_2_H, B_3_L, B_3_H, B_4_L, B_4_H, B_5_L, B_5_H, B_6_L, B_6_H, B_7_L, B_7_H, B_8_L, B_8_H, B_EOM_L, B_EOM_H, ACK} frame_state;
///////////////////////////////////
void CECFramer(int eom, unsigned char val)
{
printf("FRAME 0x%.2x, oem %d\n", val, eom);
}
int lastdur, begval;
unsigned char recv_byte;
void AnalizeT(int level, int duration)
{
// ждем старт бит
if(frame_state == B_START_L)
{
if(level == 0 && (duration >= Sbit_Min_LD && duration <= Sbit_Max_LD))
{
lastdur = duration;
frame_state++;
}
else
{
frame_state = B_START_L;
}
return;
}
if(frame_state == B_START_H)
{
if(level == 1 && (duration + lastdur) >= Sbit_Min_TD && (duration + lastdur) <= Sbit_Max_TD)
{
recv_byte = 0;
frame_state++;
}
else
{
frame_state = B_START_L;
}
return;
}
// пошли данные
int bitnum = frame_state >> 1;
if(frame_state & 1) // wait H
{
if(level != 1 || (lastdur + duration) < Dbit_Min_TD || (lastdur + duration) > Dbit_Max_TD)
{
frame_state = B_START_L;
return;
}
frame_state++;
if(frame_state == ACK) // шлем ACK
{
CECFramer(begval, recv_byte);
frame_state = B_START_L;
}
else
{
if(begval)
recv_byte |= 1 << (8 - bitnum);
}
}
else // wait L
{
if(level != 0)
{
frame_state = B_START_L;
return;
}
begval = duration < Dbit_Sample;
lastdur = duration;
frame_state++;
return;
}
}
void SendACK()
{
int timeout = timestamp + Ack_HD;
PIO_Set(&output);
while(timestamp < timeout ) ;
PIO_Clear(&output);
}
int main()
{
Pin leds[] = { PINS_LEDS };
TRACE_CONFIGURE(DBGU_STANDARD, 115200, BOARD_MCK);
printf("-- Getting Started Project %s --\n\r", SOFTPACK_VERSION);
printf("-- %s\n\r", BOARD_NAME);
printf("-- Compiled: %s %s --\n\r", __DATE__, __TIME__);
// Configuration
ConfigurePit();
Pin input = {AT91C_PIO_PA30, AT91C_BASE_PIOA, AT91C_ID_PIOA, PIO_INPUT, PIO_DEGLITCH}; // GPIO
// Pin input = {AT91C_PIO_PA30, AT91C_BASE_PIOA, AT91C_ID_PIOA, PIO_PERIPH_A, PIO_DEGLITCH}; // INT
Pin output = {AT91C_PIO_PA31, AT91C_BASE_PIOA, AT91C_ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT};
PIO_Configure(&leds[0], sizeof(leds) / sizeof(Pin));
PIO_Set(&leds[0]);
PIO_Clear(&leds[1]);
PIO_Configure(&input, 1);
PIO_Configure(&output, 1);
PIO_Clear(&output);
// AIC_ConfigureIT(AT91C_ID_IRQ1, AT91C_AIC_SRCTYPE_EXT_NEGATIVE_EDGE | AT91C_AIC_PRIOR_HIGHEST, ISR_IRQ1);
waiting_edge = 0;
lasttimestamp = 0;
// AIC_EnableIT(AT91C_ID_IRQ1);
int lasttimestamp, state, laststate = 1;
frame_state = B_START_L;
////
while(1)
{
state = PIO_Get(&input);
if(state)
{
PIO_Set(&leds[0]);
PIO_Clear(&leds[1]);
}
else
{
PIO_Set(&leds[1]);
PIO_Clear(&leds[0]);
}
if(laststate != state)
{
int val = timestamp;
AnalizeT(!state, val - lasttimestamp);
lasttimestamp = val;
}
laststate = state;
}
return 0;
}