Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Anders Blomdell
processer
Commits
8756dffa
Commit
8756dffa
authored
Oct 17, 2019
by
Anders Blomdell
Browse files
Move ADS869X code to it's own file. Add detection of I/O chips.
parent
bdabdf28
Changes
4
Hide whitespace changes
Inline
Side-by-side
china_io-2019/avr/Makefile
View file @
8756dffa
...
...
@@ -7,7 +7,7 @@ china-io.FUSE=--wr_fuse_l=0x1f --wr_fuse_h=0xd9 --wr_fuse_e=0xff
china-io.FUSE_L
=
0x1f
china-io.FUSE_H
=
0xd9
china-io.C
=
china-io
china-io.H
=
../../lib/avr/serialio i2c_master
china-io.H
=
../../lib/avr/serialio i2c_master
ads869x
china-io-test.ARCH
=
avr
china-io-test.CHIP
=
atmega32
...
...
china_io-2019/avr/ads869x.h
0 → 100644
View file @
8756dffa
#ifndef __ADS869X_H__
#define __ADS869X_H__
#define ADS869X_AUTO_SEQ_EN 0x01
#define ADS869X_FeatureSelect 0x03
#define ADS869X_REG_W(REG_ADDR, VALUE) ((REG_ADDR<<1)|0x01),(VALUE)
#define ADS869X_REG_R(REG_ADDR, VALUE) ((REG_ADDR<<1)),(VALUE)
#define ADS869X_W(W_DATA) DO_ADS869X_W_R(sizeof(W_DATA), W_DATA, \
0, NULL)
#define ADS869X_R(R_DATA) DO_ADS869X_W_R(0, NULL, \
sizeof(R_DATA), R_DATA)
#define ADS869X_W_R(W_DATA, R_DATA) DO_ADS869X_W_R(sizeof(W_DATA), W_DATA, \
sizeof(R_DATA), R_DATA)
static
uint8_t
DO_ADS869X_W_R
(
uint8_t
w_length
,
const
__flash
uint8_t
*
w_data
,
uint8_t
r_length
,
uint8_t
*
r_data
)
{
uint8_t
last_byte
;
/* Always setup SPI in case others use SPI */
DDR_SPI
|=
(
1
<<
DD_MOSI
)
|
(
1
<<
DD_SCK
)
|
(
1
<<
DD_SS
);
PORT_SPI
|=
(
1
<<
DD_MISO
);
// Pull up
SPCR
=
(
SPCR
&
(
1
<<
SPIE
))
|
(
1
<<
SPE
)
|
(
1
<<
MSTR
)
|
(
1
<<
CPHA
);
SPSR
=
(
1
<<
SPI2X
);
PORT_SPI
&=
~
(
1
<<
DD_SS
);
// Chip select
for
(
uint8_t
i
=
0
;
i
<
w_length
;
i
++
)
{
SPDR
=
w_data
[
i
];
while
((
SPSR
&
(
1
<<
SPIF
))
==
0
)
{}
last_byte
=
SPDR
;
// Clear SPIF flag
}
for
(
uint8_t
i
=
0
;
i
<
r_length
;
i
++
)
{
SPDR
=
0
;
while
((
SPSR
&
(
1
<<
SPIF
))
==
0
)
{}
last_byte
=
SPDR
;
// Clear SPIF flag
r_data
[
i
]
=
last_byte
;
}
PORT_SPI
|=
(
1
<<
DD_SS
);
// Chip deselect
return
last_byte
;
}
#endif
china_io-2019/avr/china-io-test.c
View file @
8756dffa
...
...
@@ -110,6 +110,35 @@ static const __flash struct i2c_transcation write_all[] = {
I2C_END
()
};
static
volatile
struct
dac8574_check
{
struct
dac8574_check_chan
{
uint8_t
no_pdo
[
2
];
uint8_t
pdo
[
3
];
}
chan
[
4
];
}
dac8574_check
;
static
const
__flash
struct
i2c_transcation
read_all
[]
=
{
I2C_WRITE_1
(
DAC8574ADDR
,
0x10
),
I2C_READ
(
DAC8574ADDR
,
2
,
dac8574_check
.
chan
[
0
].
no_pdo
),
I2C_WRITE_1
(
DAC8574ADDR
,
0x11
),
I2C_READ
(
DAC8574ADDR
,
3
,
dac8574_check
.
chan
[
0
].
pdo
),
I2C_WRITE_1
(
DAC8574ADDR
,
0x12
),
I2C_READ
(
DAC8574ADDR
,
2
,
dac8574_check
.
chan
[
1
].
no_pdo
),
I2C_WRITE_1
(
DAC8574ADDR
,
0x13
),
I2C_READ
(
DAC8574ADDR
,
3
,
dac8574_check
.
chan
[
1
].
pdo
),
I2C_WRITE_1
(
DAC8574ADDR
,
0x14
),
I2C_READ
(
DAC8574ADDR
,
2
,
dac8574_check
.
chan
[
2
].
no_pdo
),
I2C_WRITE_1
(
DAC8574ADDR
,
0x15
),
I2C_READ
(
DAC8574ADDR
,
3
,
dac8574_check
.
chan
[
2
].
pdo
),
I2C_WRITE_1
(
DAC8574ADDR
,
0x16
),
I2C_READ
(
DAC8574ADDR
,
2
,
dac8574_check
.
chan
[
3
].
no_pdo
),
I2C_WRITE_1
(
DAC8574ADDR
,
0x17
),
I2C_READ
(
DAC8574ADDR
,
3
,
dac8574_check
.
chan
[
3
].
pdo
),
I2C_CHAIN
(
write_all
),
I2C_END
()
};
static
volatile
int32_t
ADS8694_value
[
4
]
=
{
0
,
0
,
0
,
0
};
SIGNAL
(
TIMER1_COMPA_vect
)
...
...
@@ -210,12 +239,23 @@ int main()
}
putstr
(
"
\r
"
);
if
(
i2c_idle
())
{
putstr
(
"
\r\n
"
);
for
(
uint8_t
i
=
0
;
i
<
4
;
i
++
)
{
for
(
int
j
=
0
;
j
<
2
;
j
++
)
{
puthex
(
dac8574_check
.
chan
[
i
].
no_pdo
[
j
]);
}
putch
(
' '
);
for
(
int
j
=
0
;
j
<
3
;
j
++
)
{
puthex
(
dac8574_check
.
chan
[
i
].
pdo
[
j
]);
}
putch
(
','
);
}
cli
();
*
dac8574
.
a
.
reg
.
data
=
*
tmp
.
a
.
reg
.
data
;
*
dac8574
.
b
.
reg
.
data
=
*
tmp
.
b
.
reg
.
data
;
*
dac8574
.
c
.
reg
.
data
=
*
tmp
.
c
.
reg
.
data
;
*
dac8574
.
d
.
reg
.
data
=
*
tmp
.
d
.
reg
.
data
;
i2c_start
(
write
_all
);
i2c_start
(
read
_all
);
sei
();
putstr
(
"
\r\n
"
);
}
...
...
china_io-2019/avr/china-io.c
View file @
8756dffa
...
...
@@ -5,26 +5,13 @@
#include
"i2c_master.h"
#include
"serialio.h"
/*
* Serial I/O assignments:
*
* AI 0 -- Analog In 0
* AI 1 -- Analog In 1
* AI 2 -- Analog In 2
* AI 3 -- Analog In 3
*
* AO 0 -- Analog Out 0
* AO 1 -- Analog Out 1
*
*/
/*
* Used I/O pins
*
* PB4 SPI SS / ADS869
4
SPI CS
* PB5 Programming MOSI / ADS869
4
SPI SDI
* PB6 Programming MISO / ADS869
4
SPI SDO
* PB7 Programming SCK / ADS869
4
SPI SCLK
* PB4 SPI SS / ADS869
X
SPI CS
* PB5 Programming MOSI / ADS869
X
SPI SDI
* PB6 Programming MISO / ADS869
X
SPI SDO
* PB7 Programming SCK / ADS869
X
SPI SCLK
*
* PC0 I2C SCL
* PC1 I2C SDA
...
...
@@ -34,6 +21,7 @@
*
*/
/* Needed for ads869x.h definitions */
#define DDR_SPI DDRB
#define DD_MISO PB6
#define DD_MOSI PB5
...
...
@@ -41,6 +29,22 @@
#define DD_SS PB4
#define PORT_SPI PORTB
#include
"ads869x.h"
/*
* Serial I/O assignments:
*
* AI 0 -- Analog In 0
* AI 1 -- Analog In 1
* AI 2 -- Analog In 2
* AI 3 -- Analog In 3
*
* AO 0 -- Analog Out 0
* AO 1 -- Analog Out 1
*
*/
static
volatile
uint8_t
serial_readchannels
;
static
volatile
uint8_t
serial_writechannels
;
static
volatile
uint8_t
serial_readconfig
;
...
...
@@ -62,26 +66,6 @@ static volatile struct calibration {
}
channel
[
2
];
}
calibration
;
static
uint8_t
ADS8694_W
(
uint8_t
length
,
const
__flash
uint8_t
*
data
)
{
DDR_SPI
|=
(
1
<<
DD_MOSI
)
|
(
1
<<
DD_SCK
)
|
(
1
<<
DD_SS
);
SPCR
&=
(
1
<<
SPIE
);
SPCR
=
(
1
<<
SPE
)
|
(
1
<<
MSTR
)
|
(
1
<<
CPHA
);
SPSR
=
(
1
<<
SPI2X
);
PORT_SPI
|=
(
1
<<
DD_MISO
);
// Pull up
PORT_SPI
&=
~
(
1
<<
DD_SS
);
for
(
uint8_t
i
=
0
;
i
<
length
;
i
++
)
{
SPDR
=
data
[
i
];
while
((
SPSR
&
(
1
<<
SPIF
))
==
0
)
{}
}
uint8_t
dummy
=
SPDR
;
// Clear SPIF flag
PORT_SPI
|=
(
1
<<
DD_SS
);
return
dummy
;
}
/*
* DAC8574 4-channel D/A convert
*/
...
...
@@ -174,33 +158,28 @@ SIGNAL(USART_RXC_vect)
}
}
static
volatile
int16_t
timeout_timer
=
0
;
SIGNAL
(
TIMER1_COMPA_vect
)
{
unsigned
char
data
[
5
];
SPCR
=
(
1
<<
SPE
)
|
(
1
<<
MSTR
)
|
(
1
<<
CPHA
);
PORT_SPI
&=
~
(
1
<<
DD_SS
);
// Chip select
SPDR
=
0x00
;
// NOP
for
(
int
i
=
0
;
i
<
5
;
i
++
)
{
while
((
SPSR
&
0x80
)
==
0
)
{
}
data
[
i
]
=
SPDR
;
if
(
i
<
4
)
{
// More to read
SPDR
=
0
;
}
}
PORT_SPI
|=
(
1
<<
DD_SS
);
// Chip deselect
timeout_timer
++
;
static
const
__flash
uint8_t
NOP
[]
=
{
0x00
,
0x00
};
uint8_t
data
[]
=
{
0x00
,
0x00
,
0x00
};
// Write NOP and read back 3 bytes (18 bits + channel #)
ADS869X_W_R
(
NOP
,
data
);
union
{
uint32_t
i
;
u
nsigned
char
b
[
4
];
u
int8_t
b
[
4
];
}
v
;
uint8_t
chan
;
v
.
i
=
0
;
v
.
b
[
2
]
=
data
[
2
];
v
.
b
[
1
]
=
data
[
3
];
v
.
b
[
0
]
=
data
[
4
];
chan
=
(
v
.
i
>>
2
)
&
0x
f
;
v
.
b
[
2
]
=
data
[
0
];
v
.
b
[
1
]
=
data
[
1
];
v
.
b
[
0
]
=
data
[
2
];
chan
=
(
v
.
i
>>
2
)
&
0x
03
;
adc
.
value
[
chan
]
=
(
v
.
i
>>
6
);
}
...
...
@@ -213,8 +192,60 @@ static uint32_t conf_millivolt(int32_t value)
}
}
static
uint8_t
dac8574_check
()
{
static
struct
dac8574_check
{
struct
{
uint8_t
no_pdo
[
2
];
uint8_t
pdo
[
3
];
}
chan
[
4
];
}
check
;
static
const
__flash
struct
i2c_transcation
read_all
[]
=
{
I2C_WRITE_1
(
DAC8574ADDR
,
0x10
),
I2C_READ
(
DAC8574ADDR
,
2
,
check
.
chan
[
0
].
no_pdo
),
I2C_WRITE_1
(
DAC8574ADDR
,
0x11
),
I2C_READ
(
DAC8574ADDR
,
3
,
check
.
chan
[
0
].
pdo
),
I2C_WRITE_1
(
DAC8574ADDR
,
0x12
),
I2C_READ
(
DAC8574ADDR
,
2
,
check
.
chan
[
1
].
no_pdo
),
I2C_WRITE_1
(
DAC8574ADDR
,
0x13
),
I2C_READ
(
DAC8574ADDR
,
3
,
check
.
chan
[
1
].
pdo
),
I2C_WRITE_1
(
DAC8574ADDR
,
0x14
),
I2C_READ
(
DAC8574ADDR
,
2
,
check
.
chan
[
2
].
no_pdo
),
I2C_WRITE_1
(
DAC8574ADDR
,
0x15
),
I2C_READ
(
DAC8574ADDR
,
3
,
check
.
chan
[
2
].
pdo
),
I2C_WRITE_1
(
DAC8574ADDR
,
0x16
),
I2C_READ
(
DAC8574ADDR
,
2
,
check
.
chan
[
3
].
no_pdo
),
I2C_WRITE_1
(
DAC8574ADDR
,
0x17
),
I2C_READ
(
DAC8574ADDR
,
3
,
check
.
chan
[
3
].
pdo
),
I2C_CHAIN
(
write_all
),
I2C_END
()
};
// Read back channel data
timeout_timer
=
0
;
while
(
!
i2c_idle
()
&&
timeout_timer
<
14000
)
{
}
if
(
!
i2c_idle
())
{
return
0
;
}
i2c_start
(
read_all
);
// Check that channel data with and without power down are equal
timeout_timer
=
0
;
while
(
!
i2c_idle
()
&&
timeout_timer
<
14000
)
{
}
if
(
!
i2c_idle
())
{
return
0
;
}
for
(
int
i
=
0
;
i
<
4
;
i
++
)
{
if
((
check
.
chan
[
i
].
pdo
[
0
]
&
0x3f
)
!=
0x3f
)
{
return
0
;
}
if
(
check
.
chan
[
i
].
pdo
[
1
]
!=
check
.
chan
[
i
].
no_pdo
[
0
])
{
return
0
;
}
if
(
check
.
chan
[
i
].
pdo
[
2
]
!=
check
.
chan
[
i
].
no_pdo
[
1
])
{
return
0
;
}
}
return
1
;
}
int
main
()
{
static
uint8_t
in_channel_count
=
0
;
static
uint8_t
out_channel_count
=
0
;
eeprom_read_block
((
void
*
)
&
calibration
,
0
,
sizeof
(
calibration
));
if
(
calibration
.
not_valid
)
{
calibration
.
not_valid
=
0
;
...
...
@@ -243,15 +274,41 @@ int main()
TWBR
=
0x0a
;
// Max allowed master speed
TWSR
=
0x00
;
/* Setup DAC8574 (SPI setup is done in ADS8694_W) */
static
const
__flash
uint8_t
RST
[]
=
{
0x85
,
0x00
,
0x00
};
static
const
__flash
uint8_t
SEQUENCE
[]
=
{
(
0x01
<<
1
)
|
0x01
,
0x0f
,
0x00
};
static
const
__flash
uint8_t
FEATURES
[]
=
{
(
0x03
<<
1
)
|
0x01
,
0x03
,
0x00
};
static
const
__flash
uint8_t
AUTO_RST
[]
=
{
0xa0
,
0x00
,
0x00
,
0x00
,
0x00
};
ADS8694_W
(
3
,
RST
);
ADS8694_W
(
3
,
SEQUENCE
);
ADS8694_W
(
3
,
FEATURES
);
ADS8694_W
(
5
,
AUTO_RST
);
/* Check and setup ADS869X (SPI setup is done in ADS869X_W) */
static
const
__flash
uint8_t
RST
[]
=
{
0x85
,
0x00
,
0x00
};
static
const
__flash
uint8_t
SEQUENCE_READ
[]
=
{
ADS869X_REG_R
(
ADS869X_AUTO_SEQ_EN
,
0x01
),
0x00
};
static
const
__flash
uint8_t
SEQUENCE_0
[]
=
{
ADS869X_REG_W
(
ADS869X_AUTO_SEQ_EN
,
0x00
),
0x00
};
static
const
__flash
uint8_t
SEQUENCE_4
[]
=
{
ADS869X_REG_W
(
ADS869X_AUTO_SEQ_EN
,
0x0f
),
0x00
};
static
const
__flash
uint8_t
FEATURES
[]
=
{
ADS869X_REG_W
(
ADS869X_FeatureSelect
,
0x03
),
0x00
};
static
const
__flash
uint8_t
AUTO_RST
[]
=
{
0xa0
,
0x00
,
0x00
,
0x00
,
0x00
};
uint8_t
seq_bits
;
ADS869X_W
(
RST
);
seq_bits
=
ADS869X_W
(
SEQUENCE_READ
);
if
(
seq_bits
!=
0xff
)
{
in_channel_count
=
0
;
}
else
{
ADS869X_W
(
SEQUENCE_0
);
seq_bits
=
ADS869X_W
(
SEQUENCE_READ
);
if
(
seq_bits
==
0xf0
||
seq_bits
==
0x00
)
{
// ADS8694 or ADS8698
ADS869X_W
(
SEQUENCE_4
);
in_channel_count
=
4
;
}
else
{
in_channel_count
=
0
;
}
seq_bits
=
ADS869X_W
(
SEQUENCE_READ
);
if
(
seq_bits
!=
0x0f
)
{
in_channel_count
=
0
;
}
}
ADS869X_W
(
FEATURES
);
ADS869X_W
(
AUTO_RST
);
/* Setup serialio communication */
serialio_init
();
...
...
@@ -262,7 +319,11 @@ int main()
dac
.
value
[
0
]
=
0x8000
;
dac
.
value
[
1
]
=
0x8000
;
sei
();
// Global interrupt enable
sei
();
// Global interrupt enable
if
(
dac8574_check
())
{
out_channel_count
=
2
;
}
unsigned
char
readchannels
=
0
;
while
(
1
)
{
...
...
@@ -303,26 +364,18 @@ int main()
}
if
(
config
)
{
CONF_ANALOG_IN
(
0
,
CONF_RESOLUTION
(
18
));
// Analog In 0
CONF_ANALOG_IN
(
0
,
CONF_MIN
(
CONF_NEGATIVE_MILLIVOLT
(
10000
)));
CONF_ANALOG_IN
(
0
,
CONF_MAX
(
CONF_POSITIVE_MILLIVOLT
(
10000
)));
CONF_ANALOG_IN
(
1
,
CONF_RESOLUTION
(
18
));
// Analog In 1
CONF_ANALOG_IN
(
1
,
CONF_MIN
(
CONF_NEGATIVE_MILLIVOLT
(
10000
)));
CONF_ANALOG_IN
(
1
,
CONF_MAX
(
CONF_POSITIVE_MILLIVOLT
(
10000
)));
CONF_ANALOG_IN
(
2
,
CONF_RESOLUTION
(
18
));
// Analog In 2
CONF_ANALOG_IN
(
2
,
CONF_MIN
(
CONF_NEGATIVE_MILLIVOLT
(
10000
)));
CONF_ANALOG_IN
(
2
,
CONF_MAX
(
CONF_POSITIVE_MILLIVOLT
(
10000
)));
CONF_ANALOG_IN
(
3
,
CONF_RESOLUTION
(
18
));
// Analog In 3
CONF_ANALOG_IN
(
3
,
CONF_MIN
(
CONF_NEGATIVE_MILLIVOLT
(
10000
)));
CONF_ANALOG_IN
(
3
,
CONF_MAX
(
CONF_POSITIVE_MILLIVOLT
(
10000
)));
CONF_ANALOG_OUT
(
0
,
CONF_RESOLUTION
(
16
));
// Analog Out 0
CONF_ANALOG_OUT
(
0
,
CONF_MIN
(
conf_millivolt
(
calibration
.
channel
[
0
].
min
)));
CONF_ANALOG_OUT
(
0
,
CONF_MAX
(
conf_millivolt
(
calibration
.
channel
[
0
].
max
)));
CONF_ANALOG_OUT
(
1
,
CONF_RESOLUTION
(
16
));
// Analog Out 1
CONF_ANALOG_OUT
(
1
,
CONF_MIN
(
conf_millivolt
(
calibration
.
channel
[
1
].
min
)));
CONF_ANALOG_OUT
(
1
,
CONF_MAX
(
conf_millivolt
(
calibration
.
channel
[
1
].
max
)));
for
(
int
i
=
0
;
i
<
in_channel_count
;
i
++
)
{
CONF_ANALOG_IN
(
i
,
CONF_RESOLUTION
(
18
));
// Analog In 0
CONF_ANALOG_IN
(
i
,
CONF_MIN
(
CONF_NEGATIVE_MILLIVOLT
(
10000
)));
CONF_ANALOG_IN
(
i
,
CONF_MAX
(
CONF_POSITIVE_MILLIVOLT
(
10000
)));
}
for
(
int
i
=
0
;
i
<
out_channel_count
;
i
++
)
{
CONF_ANALOG_OUT
(
i
,
CONF_RESOLUTION
(
16
));
CONF_ANALOG_OUT
(
i
,
CONF_MIN
(
conf_millivolt
(
calibration
.
channel
[
i
].
min
)));
CONF_ANALOG_OUT
(
i
,
CONF_MAX
(
conf_millivolt
(
calibration
.
channel
[
i
].
max
)));
}
CONF_END
();
}
}
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment