Patch by Vasilis Kaoutsis - thanks!:
* Fixed some warnings. * Style cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21774 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,89 +1,103 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2003, Thomas Kurschel
|
* Copyright 2003, Thomas Kurschel. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
Part of DDC driver
|
/*!
|
||||||
|
Part of DDC driver
|
||||||
Main DDC communication
|
Main DDC communication
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <OS.h>
|
|
||||||
#include <KernelExport.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "ddc_int.h"
|
#include "ddc_int.h"
|
||||||
#include "ddc.h"
|
#include "ddc.h"
|
||||||
|
|
||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
|
|
||||||
// number of retries to read ddc data
|
#include <KernelExport.h>
|
||||||
#define READ_RETRIES 4
|
#include <OS.h>
|
||||||
|
|
||||||
// verify checksum of ddc data
|
#include <stdlib.h>
|
||||||
// (some monitors have a broken checksum - bad luck for them)
|
|
||||||
static status_t verify_checksum( const uint8 *data, size_t len )
|
|
||||||
|
#define READ_RETRIES 4
|
||||||
|
// number of retries to read ddc data
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*! Verify checksum of ddc data
|
||||||
|
(some monitors have a broken checksum - bad luck for them)
|
||||||
|
*/
|
||||||
|
static status_t
|
||||||
|
verify_checksum(const uint8 *data, size_t len)
|
||||||
{
|
{
|
||||||
int i;
|
uint32 index;
|
||||||
uint8 sum = 0;
|
uint8 sum = 0;
|
||||||
uint8 all_or = 0;
|
uint8 all_or = 0;
|
||||||
|
|
||||||
for( i = 0; i < len; ++i, ++data ) {
|
for (index = 0; index < len; ++index, ++data) {
|
||||||
sum += *data;
|
sum += *data;
|
||||||
all_or |= *data;
|
all_or |= *data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( all_or == 0 ) {
|
if (all_or == 0) {
|
||||||
SHOW_ERROR0( 2, "DDC information contains zeros only" );
|
SHOW_ERROR0(2, "DDC information contains zeros only");
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( sum != 0 ) {
|
if (sum != 0) {
|
||||||
SHOW_ERROR0( 2, "Checksum error of DDC information" );
|
SHOW_ERROR0(2, "Checksum error of DDC information");
|
||||||
return B_IO_ERROR;
|
return B_IO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// read ddc2 data from monitor
|
|
||||||
static status_t ddc2_read( const i2c_bus *bus, int start, uint8 *buffer, size_t len )
|
//! Read ddc2 data from monitor
|
||||||
|
static status_t
|
||||||
|
ddc2_read(const i2c_bus *bus, int start, uint8 *buffer, size_t len)
|
||||||
{
|
{
|
||||||
uint8 write_buffer[2];
|
uint8 write_buffer[2];
|
||||||
i2c_timing timing;
|
i2c_timing timing;
|
||||||
int i;
|
int i;
|
||||||
status_t res;
|
status_t res = B_OK;
|
||||||
|
|
||||||
write_buffer[0] = start & 0xff;
|
write_buffer[0] = start & 0xff;
|
||||||
write_buffer[1] = (start >> 8) & 0xff;
|
write_buffer[1] = (start >> 8) & 0xff;
|
||||||
|
|
||||||
i2c_get100k_timing( &timing );
|
i2c_get100k_timing(&timing);
|
||||||
|
|
||||||
timing.start_timeout = 550;
|
timing.start_timeout = 550;
|
||||||
timing.byte_timeout = 2200;
|
timing.byte_timeout = 2200;
|
||||||
timing.bit_timeout = 40;
|
timing.bit_timeout = 40;
|
||||||
timing.ack_start_timeout = 40;
|
timing.ack_start_timeout = 40;
|
||||||
timing.ack_timeout = 40;
|
timing.ack_timeout = 40;
|
||||||
|
|
||||||
for( i = 0; i < READ_RETRIES; ++i ) {
|
for (i = 0; i < READ_RETRIES; ++i) {
|
||||||
res = i2c_send_receive( bus, &timing,
|
res = i2c_send_receive(bus, &timing,
|
||||||
0xa0, write_buffer, start < 0x100 ? 1 : 2,
|
0xa0, write_buffer, start < 0x100 ? 1 : 2,
|
||||||
buffer, len );
|
buffer, len);
|
||||||
// don't verify checksum - it's often broken
|
// don't verify checksum - it's often broken
|
||||||
if( res == B_OK /*&& verify_checksum( buffer, len ) == B_OK*/ )
|
if (res == B_OK /*&& verify_checksum( buffer, len ) == B_OK*/)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
res = B_ERROR;
|
res = B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// reading VDIF has not been tested.
|
/*!
|
||||||
// it seems that almost noone supports VDIF which makes testing hard,
|
Reading VDIF has not been tested.
|
||||||
// but what's the point anyway?
|
it seems that almost noone supports VDIF which makes testing hard,
|
||||||
|
but what's the point anyway?
|
||||||
|
*/
|
||||||
#if 0
|
#if 0
|
||||||
static status_t ddc2_read_vdif( const i2c_bus *bus, int start,
|
static status_t
|
||||||
void **vdif, size_t *vdif_len )
|
ddc2_read_vdif(const i2c_bus *bus, int start,
|
||||||
|
void **vdif, size_t *vdif_len)
|
||||||
{
|
{
|
||||||
status_t res;
|
status_t res;
|
||||||
uint8 *data, *cur_data;
|
uint8 *data, *cur_data;
|
||||||
@@ -93,21 +107,21 @@ static status_t ddc2_read_vdif( const i2c_bus *bus, int start,
|
|||||||
*vdif = NULL;
|
*vdif = NULL;
|
||||||
*vdif_len = 0;
|
*vdif_len = 0;
|
||||||
|
|
||||||
res = ddc2_read( bus, start, buffer, 64 );
|
res = ddc2_read(bus, start, buffer, 64);
|
||||||
SHOW_INFO( 2, "%x", buffer[0] );
|
SHOW_INFO(2, "%x", buffer[0]);
|
||||||
if( res != B_OK || buffer[0] == 0 )
|
if (res != B_OK || buffer[0] == 0)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
// each block is 63 bytes plus 1 checksum long
|
// each block is 63 bytes plus 1 checksum long
|
||||||
// we strip the checksum but store data directly into
|
// we strip the checksum but store data directly into
|
||||||
// buffer, so we need an extra byte for checksum of the last block
|
// buffer, so we need an extra byte for checksum of the last block
|
||||||
data = malloc( buffer[0] * 63 + 1 );
|
data = malloc(buffer[0] * 63 + 1);
|
||||||
if( data == NULL )
|
if (data == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
cur_data = data;
|
cur_data = data;
|
||||||
for( i = 0; i < buffer[0]; ++i ) {
|
for (i = 0; i < buffer[0]; ++i) {
|
||||||
ddc2_read( bus, start + i * 64, cur_data, 64 );
|
ddc2_read(bus, start + i * 64, cur_data, 64);
|
||||||
// strip checksum byte
|
// strip checksum byte
|
||||||
cur_data += 63;
|
cur_data += 63;
|
||||||
}
|
}
|
||||||
@@ -118,29 +132,31 @@ static status_t ddc2_read_vdif( const i2c_bus *bus, int start,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// read EDID and VDIF from monitor via ddc2
|
|
||||||
status_t ddc2_read_edid1( const i2c_bus *bus, edid1_info *edid,
|
//! Read EDID and VDIF from monitor via ddc2
|
||||||
void **vdif, size_t *vdif_len )
|
status_t
|
||||||
|
ddc2_read_edid1(const i2c_bus *bus, edid1_info *edid,
|
||||||
|
void **vdif, size_t *vdif_len)
|
||||||
{
|
{
|
||||||
status_t res;
|
status_t res;
|
||||||
edid1_raw raw;
|
edid1_raw raw;
|
||||||
|
|
||||||
res = ddc2_read( bus, 0, (uint8 *)&raw, sizeof( raw ));
|
res = ddc2_read(bus, 0, (uint8 *)&raw, sizeof(raw));
|
||||||
if( res != B_OK )
|
if (res != B_OK)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
edid_decode( edid, &raw );
|
edid_decode(edid, &raw);
|
||||||
|
|
||||||
*vdif = NULL;
|
*vdif = NULL;
|
||||||
*vdif_len = 0;
|
*vdif_len = 0;
|
||||||
|
|
||||||
// skip vdif as long as it's not tested
|
// skip vdif as long as it's not tested
|
||||||
#if 0
|
#if 0
|
||||||
res = ddc2_read_vdif( bus, sizeof( raw ) * (edid->num_sections + 1),
|
res = ddc2_read_vdif(bus, sizeof(raw) * (edid->num_sections + 1),
|
||||||
vdif, vdif_len );
|
vdif, vdif_len);
|
||||||
if( res != B_OK )
|
if (res != B_OK)
|
||||||
return res;
|
return res;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,20 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2003, Thomas Kurschel
|
* Copyright 2003, Thomas Kurschel. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef DDC_INT_H
|
||||||
|
#define DDC_INT_H
|
||||||
|
|
||||||
|
|
||||||
Part of DDC driver
|
/*!
|
||||||
|
Part of DDC driver
|
||||||
Internal header
|
Internal header
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// no dprintf in user space, but if you know the trick ;)
|
|
||||||
void _sPrintf(const char *format, ...);
|
void _sPrintf(const char *format, ...);
|
||||||
|
// no dprintf in user space, but if you know the trick ;)
|
||||||
|
|
||||||
//bool set_dprintf_enabled(bool); /* returns old enable flag */
|
//bool set_dprintf_enabled(bool); /* returns old enable flag */
|
||||||
|
|
||||||
#define dprintf _sPrintf
|
#define dprintf _sPrintf
|
||||||
@@ -21,3 +27,5 @@ void _sPrintf(const char *format, ...);
|
|||||||
#define DEBUG_MSG_PREFIX "DDC "
|
#define DEBUG_MSG_PREFIX "DDC "
|
||||||
|
|
||||||
#include "debug_ext.h"
|
#include "debug_ext.h"
|
||||||
|
|
||||||
|
#endif // DDC_INT_H
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, Thomas Kurschel. All Rights Reserved.
|
* Copyright 2003, Thomas Kurschel. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Part of DDC driver
|
Part of DDC driver
|
||||||
|
|
||||||
@@ -16,6 +17,7 @@
|
|||||||
#include "edid.h"
|
#include "edid.h"
|
||||||
|
|
||||||
#include <KernelExport.h>
|
#include <KernelExport.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -89,12 +91,15 @@ decode_std_timing(edid1_std_timing *timing, const edid1_std_timing_raw *raw)
|
|||||||
case 0:
|
case 0:
|
||||||
timing->v_size = timing->h_size;
|
timing->v_size = timing->h_size;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
timing->v_size = timing->h_size * 3 / 4;
|
timing->v_size = timing->h_size * 3 / 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
timing->v_size = timing->h_size * 4 / 5;
|
timing->v_size = timing->h_size * 4 / 5;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
timing->v_size = timing->h_size * 9 / 16;
|
timing->v_size = timing->h_size * 9 / 16;
|
||||||
break;
|
break;
|
||||||
@@ -120,7 +125,7 @@ decode_whitepoint(edid1_whitepoint *whitepoint, const edid1_whitepoint_raw *raw)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
decode_detailed_timing( edid1_detailed_timing *timing,
|
decode_detailed_timing(edid1_detailed_timing *timing,
|
||||||
const edid1_detailed_timing_raw *raw)
|
const edid1_detailed_timing_raw *raw)
|
||||||
{
|
{
|
||||||
timing->pixel_clock = raw->pixel_clock;
|
timing->pixel_clock = raw->pixel_clock;
|
||||||
@@ -168,7 +173,7 @@ copy_str(char *dest, const uint8 *src, size_t len)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
decode_detailed_monitor( edid1_detailed_monitor *monitor,
|
decode_detailed_monitor(edid1_detailed_monitor *monitor,
|
||||||
const edid1_detailed_monitor_raw *raw, bool enableExtra)
|
const edid1_detailed_monitor_raw *raw, bool enableExtra)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
@@ -191,21 +196,26 @@ decode_detailed_monitor( edid1_detailed_monitor *monitor,
|
|||||||
copy_str( monitor->data.serial_number,
|
copy_str( monitor->data.serial_number,
|
||||||
raw->extra.data.serial_number, EDID1_EXTRA_STRING_LEN );
|
raw->extra.data.serial_number, EDID1_EXTRA_STRING_LEN );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case edid1_ascii_data:
|
case edid1_ascii_data:
|
||||||
copy_str( monitor->data.ascii_data,
|
copy_str( monitor->data.ascii_data,
|
||||||
raw->extra.data.ascii_data, EDID1_EXTRA_STRING_LEN );
|
raw->extra.data.ascii_data, EDID1_EXTRA_STRING_LEN );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case edid1_monitor_ranges:
|
case edid1_monitor_ranges:
|
||||||
monitor->data.monitor_range = raw->extra.data.monitor_range;
|
monitor->data.monitor_range = raw->extra.data.monitor_range;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case edid1_monitor_name:
|
case edid1_monitor_name:
|
||||||
copy_str( monitor->data.monitor_name,
|
copy_str( monitor->data.monitor_name,
|
||||||
raw->extra.data.monitor_name, EDID1_EXTRA_STRING_LEN );
|
raw->extra.data.monitor_name, EDID1_EXTRA_STRING_LEN );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case edid1_add_colour_pointer:
|
case edid1_add_colour_pointer:
|
||||||
decode_whitepoint( monitor->data.whitepoint,
|
decode_whitepoint( monitor->data.whitepoint,
|
||||||
&raw->extra.data.whitepoint );
|
&raw->extra.data.whitepoint );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case edid1_add_std_timing:
|
case edid1_add_std_timing:
|
||||||
for (j = 0; j < EDID1_NUM_EXTRA_STD_TIMING; ++j) {
|
for (j = 0; j < EDID1_NUM_EXTRA_STD_TIMING; ++j) {
|
||||||
decode_std_timing(&monitor->data.std_timing[j],
|
decode_std_timing(&monitor->data.std_timing[j],
|
||||||
@@ -224,7 +234,7 @@ decode_detailed_monitor( edid1_detailed_monitor *monitor,
|
|||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
//! main function to decode edid data
|
//! Main function to decode edid data
|
||||||
void
|
void
|
||||||
edid_decode(edid1_info *edid, const edid1_raw *raw)
|
edid_decode(edid1_info *edid, const edid1_raw *raw)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,11 +3,13 @@
|
|||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Part of DDC driver
|
Part of DDC driver
|
||||||
Dumps EDID content
|
Dumps EDID content
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "edid.h"
|
#include "edid.h"
|
||||||
#if !defined(_KERNEL_MODE) && !defined(_BOOT_MODE)
|
#if !defined(_KERNEL_MODE) && !defined(_BOOT_MODE)
|
||||||
# include "ddc_int.h"
|
# include "ddc_int.h"
|
||||||
@@ -91,10 +93,13 @@ edid_dump(edid1_info *edid)
|
|||||||
case edid1_serial_number:
|
case edid1_serial_number:
|
||||||
dprintf("Serial Number: %s\n", monitor->data.serial_number);
|
dprintf("Serial Number: %s\n", monitor->data.serial_number);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case edid1_ascii_data:
|
case edid1_ascii_data:
|
||||||
dprintf(" %s\n", monitor->data.serial_number);
|
dprintf(" %s\n", monitor->data.serial_number);
|
||||||
break;
|
break;
|
||||||
case edid1_monitor_ranges: {
|
|
||||||
|
case edid1_monitor_ranges:
|
||||||
|
{
|
||||||
edid1_monitor_range monitor_range = monitor->data.monitor_range;
|
edid1_monitor_range monitor_range = monitor->data.monitor_range;
|
||||||
|
|
||||||
dprintf("Horizontal frequency range = %d..%d kHz\n",
|
dprintf("Horizontal frequency range = %d..%d kHz\n",
|
||||||
@@ -104,10 +109,13 @@ edid_dump(edid1_info *edid)
|
|||||||
dprintf("Maximum pixel clock = %d MHz\n", (uint16)monitor_range.max_clock * 10);
|
dprintf("Maximum pixel clock = %d MHz\n", (uint16)monitor_range.max_clock * 10);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case edid1_monitor_name:
|
case edid1_monitor_name:
|
||||||
dprintf("Monitor Name: %s\n", monitor->data.serial_number);
|
dprintf("Monitor Name: %s\n", monitor->data.serial_number);
|
||||||
break;
|
break;
|
||||||
case edid1_add_colour_pointer: {
|
|
||||||
|
case edid1_add_colour_pointer:
|
||||||
|
{
|
||||||
for (j = 0; j < EDID1_NUM_EXTRA_WHITEPOINTS; ++j) {
|
for (j = 0; j < EDID1_NUM_EXTRA_WHITEPOINTS; ++j) {
|
||||||
edid1_whitepoint *whitepoint = &monitor->data.whitepoint[j];
|
edid1_whitepoint *whitepoint = &monitor->data.whitepoint[j];
|
||||||
|
|
||||||
@@ -122,7 +130,9 @@ edid_dump(edid1_info *edid)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case edid1_add_std_timing: {
|
|
||||||
|
case edid1_add_std_timing:
|
||||||
|
{
|
||||||
for (j = 0; j < EDID1_NUM_EXTRA_STD_TIMING; ++j) {
|
for (j = 0; j < EDID1_NUM_EXTRA_STD_TIMING; ++j) {
|
||||||
edid1_std_timing *timing = &monitor->data.std_timing[j];
|
edid1_std_timing *timing = &monitor->data.std_timing[j];
|
||||||
|
|
||||||
@@ -135,9 +145,11 @@ edid_dump(edid1_info *edid)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case edid1_is_detailed_timing: {
|
|
||||||
|
case edid1_is_detailed_timing:
|
||||||
|
{
|
||||||
edid1_detailed_timing *timing = &monitor->data.detailed_timing;
|
edid1_detailed_timing *timing = &monitor->data.detailed_timing;
|
||||||
|
|
||||||
dprintf("Additional Video Mode:\n");
|
dprintf("Additional Video Mode:\n");
|
||||||
dprintf("clock=%f MHz\n", timing->pixel_clock / 100.0);
|
dprintf("clock=%f MHz\n", timing->pixel_clock / 100.0);
|
||||||
dprintf("h: (%d, %d, %d, %d)\n",
|
dprintf("h: (%d, %d, %d, %d)\n",
|
||||||
|
|||||||
@@ -1,215 +1,227 @@
|
|||||||
/*
|
/*
|
||||||
Copyright (c) 2003, Thomas Kurschel
|
* Copyright 2003, Thomas Kurschel. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
Part of DDC driver
|
/*!
|
||||||
|
Part of DDC driver
|
||||||
I2C protocoll
|
I2C protocoll
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <OS.h>
|
#include "ddc_int.h"
|
||||||
#include <KernelExport.h>
|
|
||||||
|
|
||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
|
|
||||||
#include "ddc_int.h"
|
#include <KernelExport.h>
|
||||||
|
#include <OS.h>
|
||||||
|
|
||||||
|
|
||||||
// there's no spin in user space, but we need it to wait a couple
|
/*!
|
||||||
// of microseconds only
|
There's no spin in user space, but we need it to wait a couple
|
||||||
// (in this case, snooze has much too much overhead)
|
of microseconds only
|
||||||
void spin( bigtime_t delay )
|
(in this case, snooze has much too much overhead)
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
spin(bigtime_t delay)
|
||||||
{
|
{
|
||||||
bigtime_t start_time = system_time();
|
bigtime_t start_time = system_time();
|
||||||
|
|
||||||
while( system_time() - start_time < delay )
|
while (system_time() - start_time < delay)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// wait until slave releases clock signal ("clock stretching")
|
//! Wait until slave releases clock signal ("clock stretching")
|
||||||
static status_t wait_for_clk( const i2c_bus *bus, const i2c_timing *timing,
|
static status_t
|
||||||
bigtime_t timeout )
|
wait_for_clk(const i2c_bus *bus, const i2c_timing *timing,
|
||||||
|
bigtime_t timeout)
|
||||||
{
|
{
|
||||||
bigtime_t start_time;
|
bigtime_t start_time;
|
||||||
|
|
||||||
// wait for clock signal to raise
|
// wait for clock signal to raise
|
||||||
spin( timing->r );
|
spin(timing->r);
|
||||||
|
|
||||||
start_time = system_time();
|
start_time = system_time();
|
||||||
|
|
||||||
while( 1 ) {
|
while (1) {
|
||||||
int clk, data;
|
int clk, data;
|
||||||
|
|
||||||
bus->get_signals( bus->cookie, &clk, &data );
|
bus->get_signals(bus->cookie, &clk, &data);
|
||||||
if( clk != 0 )
|
if (clk != 0)
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
if( system_time() - start_time > timeout )
|
if (system_time() - start_time > timeout)
|
||||||
return B_TIMEOUT;
|
return B_TIMEOUT;
|
||||||
|
|
||||||
spin( timing->r );
|
spin(timing->r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// send start or repeated start condition
|
//! Send start or repeated start condition
|
||||||
static status_t send_start_condition( const i2c_bus *bus, const i2c_timing *timing )
|
static status_t
|
||||||
|
send_start_condition(const i2c_bus *bus, const i2c_timing *timing)
|
||||||
{
|
{
|
||||||
status_t res;
|
status_t res;
|
||||||
|
|
||||||
bus->set_signals( bus->cookie, 1, 1 );
|
bus->set_signals(bus->cookie, 1, 1);
|
||||||
|
|
||||||
res = wait_for_clk( bus, timing, timing->start_timeout );
|
res = wait_for_clk(bus, timing, timing->start_timeout);
|
||||||
if( res != B_OK ) {
|
if (res != B_OK) {
|
||||||
SHOW_FLOW0( 3, "Timeout sending start condition" );
|
SHOW_FLOW0(3, "Timeout sending start condition");
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin( timing->su_sta );
|
spin(timing->su_sta);
|
||||||
bus->set_signals( bus->cookie, 1, 0 );
|
bus->set_signals(bus->cookie, 1, 0);
|
||||||
spin( timing->hd_sta );
|
spin(timing->hd_sta);
|
||||||
bus->set_signals( bus->cookie, 0, 0 );
|
bus->set_signals(bus->cookie, 0, 0);
|
||||||
spin( timing->f );
|
spin(timing->f);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// send stop condition
|
//! Send stop condition
|
||||||
static status_t send_stop_condition( const i2c_bus *bus, const i2c_timing *timing )
|
static status_t
|
||||||
|
send_stop_condition(const i2c_bus *bus, const i2c_timing *timing)
|
||||||
{
|
{
|
||||||
status_t res;
|
status_t res;
|
||||||
|
|
||||||
bus->set_signals( bus->cookie, 0, 0 );
|
bus->set_signals(bus->cookie, 0, 0);
|
||||||
spin( timing->r );
|
spin(timing->r);
|
||||||
bus->set_signals( bus->cookie, 1, 0 );
|
bus->set_signals(bus->cookie, 1, 0);
|
||||||
|
|
||||||
// a slave may wait for us, so let elapse the acknowledge timeout
|
// a slave may wait for us, so let elapse the acknowledge timeout
|
||||||
// to make the slave release bus control
|
// to make the slave release bus control
|
||||||
res = wait_for_clk( bus, timing, timing->ack_timeout );
|
res = wait_for_clk(bus, timing, timing->ack_timeout);
|
||||||
if( res != B_OK ) {
|
if (res != B_OK) {
|
||||||
SHOW_FLOW0( 3, "Timeout sending stop condition" );
|
SHOW_FLOW0(3, "Timeout sending stop condition");
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin( timing->su_sto );
|
spin(timing->su_sto);
|
||||||
bus->set_signals( bus->cookie, 1, 1 );
|
bus->set_signals(bus->cookie, 1, 1);
|
||||||
spin( timing->buf );
|
spin(timing->buf);
|
||||||
|
|
||||||
SHOW_FLOW0( 3, "" );
|
SHOW_FLOW0(3, "");
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// send one bit
|
//! Send one bit
|
||||||
static status_t send_bit( const i2c_bus *bus, const i2c_timing *timing, bool bit, int timeout )
|
static status_t
|
||||||
|
send_bit(const i2c_bus *bus, const i2c_timing *timing, bool bit, int timeout)
|
||||||
{
|
{
|
||||||
status_t res;
|
status_t res;
|
||||||
|
|
||||||
//SHOW_FLOW( 3, "%d", bit & 1 );
|
//SHOW_FLOW( 3, "%d", bit & 1 );
|
||||||
|
|
||||||
bus->set_signals( bus->cookie, 0, bit & 1 );
|
bus->set_signals(bus->cookie, 0, bit & 1);
|
||||||
spin( timing->su_dat );
|
spin(timing->su_dat);
|
||||||
bus->set_signals( bus->cookie, 1, bit & 1 );
|
bus->set_signals(bus->cookie, 1, bit & 1);
|
||||||
|
|
||||||
res = wait_for_clk( bus, timing, timeout );
|
res = wait_for_clk(bus, timing, timeout);
|
||||||
if( res != B_OK ) {
|
if (res != B_OK) {
|
||||||
SHOW_FLOW0( 3, "Timeout when sending next bit" );
|
SHOW_FLOW0(3, "Timeout when sending next bit");
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin( timing->high );
|
|
||||||
bus->set_signals( bus->cookie, 0, bit & 1 );
|
|
||||||
spin( timing->f + timing->low );
|
|
||||||
|
|
||||||
|
spin(timing->high);
|
||||||
|
bus->set_signals(bus->cookie, 0, bit & 1);
|
||||||
|
spin(timing->f + timing->low);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// send acknowledge and wait for reply
|
//! Send acknowledge and wait for reply
|
||||||
static status_t send_acknowledge( const i2c_bus *bus, const i2c_timing *timing )
|
static status_t
|
||||||
|
send_acknowledge(const i2c_bus *bus, const i2c_timing *timing)
|
||||||
{
|
{
|
||||||
status_t res;
|
status_t res;
|
||||||
bigtime_t start_time;
|
bigtime_t start_time;
|
||||||
|
|
||||||
// release data so slave can modify it
|
// release data so slave can modify it
|
||||||
bus->set_signals( bus->cookie, 0, 1 );
|
bus->set_signals(bus->cookie, 0, 1);
|
||||||
spin( timing->su_dat );
|
spin(timing->su_dat);
|
||||||
bus->set_signals( bus->cookie, 1, 1 );
|
bus->set_signals(bus->cookie, 1, 1);
|
||||||
|
|
||||||
res = wait_for_clk( bus, timing, timing->ack_start_timeout );
|
res = wait_for_clk(bus, timing, timing->ack_start_timeout);
|
||||||
if( res != B_OK ) {
|
if (res != B_OK) {
|
||||||
SHOW_FLOW0( 3, "Timeout when sending acknowledge" );
|
SHOW_FLOW0(3, "Timeout when sending acknowledge");
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// data and clock is high, now wait for slave to pull data low
|
// data and clock is high, now wait for slave to pull data low
|
||||||
// (according to spec, this can happen any time once clock is high)
|
// (according to spec, this can happen any time once clock is high)
|
||||||
start_time = system_time();
|
start_time = system_time();
|
||||||
|
|
||||||
while( 1 ) {
|
while (1) {
|
||||||
int clk, data;
|
int clk, data;
|
||||||
|
|
||||||
bus->get_signals( bus->cookie, &clk, &data );
|
bus->get_signals(bus->cookie, &clk, &data);
|
||||||
|
|
||||||
if( data == 0 )
|
if (data == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if( system_time() - start_time > timing->ack_timeout ) {
|
if (system_time() - start_time > timing->ack_timeout) {
|
||||||
SHOW_FLOW0( 3, "Slave didn't acknowledge byte" );
|
SHOW_FLOW0(3, "Slave didn't acknowledge byte");
|
||||||
return B_TIMEOUT;
|
return B_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin( timing->r );
|
spin(timing->r);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHOW_FLOW0( 4, "Success!" );
|
|
||||||
|
|
||||||
// make sure we've waited at least t_high
|
|
||||||
spin( timing->high );
|
|
||||||
|
|
||||||
bus->set_signals( bus->cookie, 0, 1 );
|
SHOW_FLOW0(4, "Success!");
|
||||||
spin( timing->f + timing->low );
|
|
||||||
|
// make sure we've waited at least t_high
|
||||||
|
spin(timing->high);
|
||||||
|
|
||||||
|
bus->set_signals(bus->cookie, 0, 1);
|
||||||
|
spin(timing->f + timing->low);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// send byte and wait for acknowledge if <ackowledge> is true
|
//! Send byte and wait for acknowledge if <ackowledge> is true
|
||||||
static status_t send_byte( const i2c_bus *bus, const i2c_timing *timing,
|
static status_t
|
||||||
uint8 byte, bool acknowledge )
|
send_byte(const i2c_bus *bus, const i2c_timing *timing,
|
||||||
|
uint8 byte, bool acknowledge)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
SHOW_FLOW( 3, "%x ", byte );
|
SHOW_FLOW( 3, "%x ", byte );
|
||||||
|
|
||||||
for( i = 7; i >= 0; --i ) {
|
for (i = 7; i >= 0; --i) {
|
||||||
status_t res;
|
status_t res;
|
||||||
|
|
||||||
res = send_bit( bus, timing, byte >> i,
|
res = send_bit(bus, timing, byte >> i,
|
||||||
i == 7 ? timing->byte_timeout : timing->bit_timeout );
|
i == 7 ? timing->byte_timeout : timing->bit_timeout);
|
||||||
if( res != B_OK )
|
if (res != B_OK)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( acknowledge )
|
if (acknowledge)
|
||||||
return send_acknowledge( bus, timing );
|
return send_acknowledge(bus, timing);
|
||||||
else
|
else
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// send slave address, obeying 10-bit addresses and general call addresses
|
|
||||||
static status_t send_slave_address( const i2c_bus *bus,
|
//! Send slave address, obeying 10-bit addresses and general call addresses
|
||||||
const i2c_timing *timing, int slave_address, bool is_write )
|
static status_t
|
||||||
|
send_slave_address( const i2c_bus *bus, const i2c_timing *timing,
|
||||||
|
int slave_address, bool is_write )
|
||||||
{
|
{
|
||||||
status_t res;
|
status_t res;
|
||||||
|
|
||||||
res = send_byte( bus, timing, (slave_address & 0xfe) | !is_write, true );
|
res = send_byte(bus, timing, (slave_address & 0xfe) | !is_write, true);
|
||||||
if( res != B_OK )
|
if (res != B_OK)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
// there are the following special cases if the first byte looks like:
|
// there are the following special cases if the first byte looks like:
|
||||||
// - 0000 0000 - general call address (second byte with address follows)
|
// - 0000 0000 - general call address (second byte with address follows)
|
||||||
// - 0000 0001 - start byte
|
// - 0000 0001 - start byte
|
||||||
@@ -221,154 +233,166 @@ static status_t send_slave_address( const i2c_bus *bus,
|
|||||||
// - 1111 0xxx - 10 bit address (second byte contains remaining 8 bits)
|
// - 1111 0xxx - 10 bit address (second byte contains remaining 8 bits)
|
||||||
|
|
||||||
// the lsb is 0 for write and 1 for read (except for general call address)
|
// the lsb is 0 for write and 1 for read (except for general call address)
|
||||||
if( (slave_address & 0xff) != 0 &&
|
if ((slave_address & 0xff) != 0 && (slave_address & 0xf8) != 0xf0)
|
||||||
(slave_address & 0xf8) != 0xf0 )
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
// send second byte if required
|
return send_byte(bus, timing, slave_address >> 8, true);
|
||||||
return send_byte( bus, timing, slave_address >> 8, true );
|
// send second byte if required
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// receive one bit
|
//! Receive one bit
|
||||||
static status_t receive_bit( const i2c_bus *bus, const i2c_timing *timing,
|
static status_t
|
||||||
bool *bit, int timeout )
|
receive_bit(const i2c_bus *bus, const i2c_timing *timing,
|
||||||
|
bool *bit, int timeout)
|
||||||
{
|
{
|
||||||
status_t res;
|
status_t res;
|
||||||
int clk, data;
|
int clk, data;
|
||||||
|
|
||||||
// release clock
|
bus->set_signals(bus->cookie, 1, 1);
|
||||||
bus->set_signals( bus->cookie, 1, 1 );
|
// release clock
|
||||||
|
|
||||||
// wait for slave to raise clock
|
// wait for slave to raise clock
|
||||||
res = wait_for_clk( bus, timing, timeout );
|
res = wait_for_clk(bus, timing, timeout);
|
||||||
if( res != B_OK ) {
|
if (res != B_OK) {
|
||||||
SHOW_FLOW0( 3, "Timeout waiting for bit sent by slave" );
|
SHOW_FLOW0(3, "Timeout waiting for bit sent by slave");
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sample data
|
bus->get_signals(bus->cookie, &clk, &data);
|
||||||
bus->get_signals( bus->cookie, &clk, &data );
|
// sample data
|
||||||
// leave clock high for minimal time
|
|
||||||
spin( timing->high );
|
spin(timing->high);
|
||||||
// pull clock low so slave waits for us before next bit
|
// leave clock high for minimal time
|
||||||
bus->set_signals( bus->cookie, 0, 1 );
|
|
||||||
// let it settle and leave it low for minimal time
|
bus->set_signals(bus->cookie, 0, 1);
|
||||||
// to make sure slave has finished bit transmission too
|
// pull clock low so slave waits for us before next bit
|
||||||
spin( timing->f + timing->low);
|
|
||||||
|
spin(timing->f + timing->low);
|
||||||
|
// let it settle and leave it low for minimal time
|
||||||
|
// to make sure slave has finished bit transmission too
|
||||||
|
|
||||||
*bit = data;
|
*bit = data;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// receive byte
|
|
||||||
// send positive acknowledge afterwards if <acknowledge> is true, else send negative one
|
/*! receive byte
|
||||||
static status_t receive_byte( const i2c_bus *bus, const i2c_timing *timing,
|
Send positive acknowledge afterwards if <acknowledge> is true,
|
||||||
uint8 *res_byte, bool acknowledge )
|
else send negative one
|
||||||
|
*/
|
||||||
|
static status_t
|
||||||
|
receive_byte(const i2c_bus *bus, const i2c_timing *timing,
|
||||||
|
uint8 *res_byte, bool acknowledge)
|
||||||
{
|
{
|
||||||
uint8 byte = 0;
|
uint8 byte = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// pull clock low to let slave wait for us
|
|
||||||
bus->set_signals( bus->cookie, 0, 1 );
|
|
||||||
|
|
||||||
for( i = 7; i >= 0; --i ) {
|
// pull clock low to let slave wait for us
|
||||||
|
bus->set_signals(bus->cookie, 0, 1);
|
||||||
|
|
||||||
|
for (i = 7; i >= 0; --i) {
|
||||||
status_t res;
|
status_t res;
|
||||||
bool bit;
|
bool bit;
|
||||||
|
|
||||||
res = receive_bit( bus, timing, &bit,
|
res = receive_bit(bus, timing, &bit,
|
||||||
i == 7 ? timing->byte_timeout : timing->bit_timeout );
|
i == 7 ? timing->byte_timeout : timing->bit_timeout);
|
||||||
if( res != B_OK )
|
if (res != B_OK)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
byte = (byte << 1) | bit;
|
byte = (byte << 1) | bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
//SHOW_FLOW( 3, "%x ", byte );
|
//SHOW_FLOW( 3, "%x ", byte );
|
||||||
|
|
||||||
*res_byte = byte;
|
*res_byte = byte;
|
||||||
|
|
||||||
return send_bit( bus, timing, acknowledge ? 0 : 1, timing->bit_timeout );
|
return send_bit(bus, timing, acknowledge ? 0 : 1, timing->bit_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
// send multiple bytes
|
|
||||||
static status_t send_bytes( const i2c_bus *bus, const i2c_timing *timing,
|
//! Send multiple bytes
|
||||||
const uint8 *write_buffer, ssize_t write_len )
|
static status_t
|
||||||
|
send_bytes(const i2c_bus *bus, const i2c_timing *timing,
|
||||||
|
const uint8 *write_buffer, ssize_t write_len)
|
||||||
{
|
{
|
||||||
SHOW_FLOW( 3, "len=%ld", write_len );
|
SHOW_FLOW( 3, "len=%ld", write_len );
|
||||||
|
|
||||||
for( ; write_len > 0; --write_len, ++write_buffer ) {
|
for (; write_len > 0; --write_len, ++write_buffer) {
|
||||||
status_t res;
|
status_t res;
|
||||||
|
|
||||||
res = send_byte( bus, timing, *write_buffer, true );
|
res = send_byte(bus, timing, *write_buffer, true);
|
||||||
if( res != B_OK )
|
if (res != B_OK)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// receive multiple bytes
|
|
||||||
static status_t receive_bytes( const i2c_bus *bus, const i2c_timing *timing,
|
//! Receive multiple bytes
|
||||||
uint8 *read_buffer, ssize_t read_len )
|
static status_t
|
||||||
|
receive_bytes(const i2c_bus *bus, const i2c_timing *timing,
|
||||||
|
uint8 *read_buffer, ssize_t read_len)
|
||||||
{
|
{
|
||||||
SHOW_FLOW( 3, "len=%ld", read_len );
|
SHOW_FLOW(3, "len=%ld", read_len);
|
||||||
|
|
||||||
for( ; read_len > 0; --read_len, ++read_buffer ) {
|
for (; read_len > 0; --read_len, ++read_buffer) {
|
||||||
status_t res;
|
status_t res;
|
||||||
|
|
||||||
res = receive_byte( bus, timing, read_buffer, read_len > 1 );
|
res = receive_byte(bus, timing, read_buffer, read_len > 1);
|
||||||
if( res != B_OK )
|
if (res != B_OK)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// combined i2c send+receive format
|
|
||||||
status_t i2c_send_receive( const i2c_bus *bus, const i2c_timing *timing,
|
//! Combined i2c send+receive format
|
||||||
int slave_address,
|
status_t
|
||||||
const uint8 *write_buffer, size_t write_len,
|
i2c_send_receive(const i2c_bus *bus, const i2c_timing *timing,
|
||||||
uint8 *read_buffer, size_t read_len )
|
int slave_address, const uint8 *write_buffer, size_t write_len,
|
||||||
|
uint8 *read_buffer, size_t read_len)
|
||||||
{
|
{
|
||||||
status_t res;
|
status_t res;
|
||||||
|
|
||||||
res = send_start_condition( bus, timing );
|
res = send_start_condition(bus, timing);
|
||||||
if( res != B_OK )
|
if (res != B_OK)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
res = send_slave_address( bus, timing, slave_address, true );
|
res = send_slave_address(bus, timing, slave_address, true);
|
||||||
if( res != B_OK )
|
if (res != B_OK)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
res = send_bytes( bus, timing, write_buffer, write_len );
|
res = send_bytes(bus, timing, write_buffer, write_len);
|
||||||
if( res != B_OK )
|
if (res != B_OK)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
res = send_start_condition( bus, timing );
|
res = send_start_condition(bus, timing);
|
||||||
if( res != B_OK )
|
if (res != B_OK)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
res = send_slave_address( bus, timing, slave_address, false );
|
res = send_slave_address(bus, timing, slave_address, false);
|
||||||
if( res != B_OK )
|
if (res != B_OK)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
res = receive_bytes( bus, timing, read_buffer, read_len );
|
res = receive_bytes(bus, timing, read_buffer, read_len);
|
||||||
if( res != B_OK )
|
if (res != B_OK)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
res = send_stop_condition( bus, timing );
|
res = send_stop_condition(bus, timing);
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
SHOW_FLOW0( 3, "Cancelling transmission" );
|
SHOW_FLOW0(3, "Cancelling transmission");
|
||||||
send_stop_condition( bus, timing );
|
send_stop_condition(bus, timing);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
// timining for 100kHz bus (fractional parts are rounded up)
|
|
||||||
i2c_timing i2c_timing_100k =
|
//! Timining for 100kHz bus (fractional parts are rounded up)
|
||||||
{
|
i2c_timing i2c_timing_100k = {
|
||||||
buf : 5,
|
buf : 5,
|
||||||
hd_sta : 4,
|
hd_sta : 4,
|
||||||
low : 5,
|
low : 5,
|
||||||
@@ -390,8 +414,7 @@ i2c_timing i2c_timing_100k =
|
|||||||
|
|
||||||
// timing for 400 kHz bus
|
// timing for 400 kHz bus
|
||||||
// (argh! heavy up-rounding here)
|
// (argh! heavy up-rounding here)
|
||||||
i2c_timing i2c_timing_400k =
|
i2c_timing i2c_timing_400k = {
|
||||||
{
|
|
||||||
buf : 2,
|
buf : 2,
|
||||||
hd_sta : 1,
|
hd_sta : 1,
|
||||||
low : 2,
|
low : 2,
|
||||||
@@ -411,12 +434,16 @@ i2c_timing i2c_timing_400k =
|
|||||||
ack_timeout : 2
|
ack_timeout : 2
|
||||||
};
|
};
|
||||||
|
|
||||||
void i2c_get100k_timing( i2c_timing *timing )
|
|
||||||
|
void
|
||||||
|
i2c_get100k_timing(i2c_timing *timing)
|
||||||
{
|
{
|
||||||
*timing = i2c_timing_100k;
|
*timing = i2c_timing_100k;
|
||||||
}
|
}
|
||||||
|
|
||||||
void i2c_get400k_timing( i2c_timing *timing )
|
|
||||||
|
void
|
||||||
|
i2c_get400k_timing(i2c_timing *timing)
|
||||||
{
|
{
|
||||||
*timing = i2c_timing_400k;
|
*timing = i2c_timing_400k;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user