This is an alternate version of the 99-01-TCS3200-color-detector that uses the class _tcs3200
provided by HWA.
#include "config.h"
#if ! defined BOARD_TCS3200
# error Incompatible board
#endif
#define hw_sensor0 _tcs3200, 0, 0
#define hw_sensor0_s2 PIN_TCS3200_S2
#define hw_sensor0_s3 PIN_TCS3200_S3
uint16_t tclear_max ;
typedef struct {
uint8_t radius ;
uint8_t red, green, blue ;
uint8_t id ;
} region_t ;
uint8_t uart_getbyte ( )
{
while ( !
hw(stat,UART).rxc )
}
void uart_putbyte ( uint8_t byte )
{
while ( !
hw(stat,UART).txc )
}
static uint16_t measure ( )
{
uint16_t t ;
hw( write, COMPARE,
hw(read, COUNTER) );
hw( clear, (COMPARE,irq) );
hw( configure, CAPTURE, edge, rising );
hw( clear, (CAPTURE,irq) );
for (;;) {
if (
hw( read, (CAPTURE,irq) ) )
break ;
if (
hw( read, (COMPARE,irq) ) )
return 0xFFFF ;
}
t =
hw( read, CAPTURE ) ;
hw( clear, (COMPARE,irq) );
hw( configure, CAPTURE, edge, falling );
hw( clear, (CAPTURE,irq) );
for (;;) {
if (
hw( read, (CAPTURE,irq) ) )
return hw( read, CAPTURE ) - t ;
if (
hw( read, (COMPARE,irq) ) )
return 0xFFFF ;
}
}
static uint8_t ishex ( uint8_t h )
{
return (h>='0' && h<='9') || (h>='A' && h<='F') ;
}
static void tx1h ( uint8_t n )
{
if ( n < 10 )
n = n + '0' ;
else
n = n - 10 + 'A' ;
uart_putbyte( n );
}
static void tx2h ( uint8_t n )
{
tx1h( (n>>4) & 0x0F );
tx1h( (n>>0) & 0x0F );
}
static void tx4h ( uint16_t n )
{
tx2h( (n>>0) & 0xFF );
tx2h( (n>>8) & 0xFF );
}
static uint8_t H2i ( uint8_t c )
{
if ( c<='9' )
return c-'0' ;
return 10+c-'A' ;
}
static uint8_t HH2i ( uint8_t s[] )
{
return (H2i(s[0])<<4) + H2i(s[1]) ;
}
static uint16_t HHHH2i ( uint8_t s[] )
{
uint16_t r = HH2i(&s[2]);
r <<= 8 ;
r |= HH2i(&s[0]) ;
return r ;
}
int
main ( )
{
hwa( configure, CAPTURE, input, pin_icp );
hwa( configure, PIN_TCS3200_S2, mode, digital_output );
hwa( configure, PIN_TCS3200_S3, mode, digital_output );
hwa( configure, PIN_OUTS, mode, digital_output );
hwa( write, PIN_OUTS, 0 );
hw( enable, interrupts );
hw( read_bytes, eeprom0, &tclear_max, &ee_tclear_max,
sizeof(tclear_max) );
uint16_t tclear ;
uint16_t tred ;
uint16_t tgreen ;
uint16_t tblue ;
uint32_t pred ;
uint32_t pgreen ;
uint32_t pblue ;
for(;;) {
uint8_t rn ;
hw( configure, sensor0, filter, clear ); tclear = measure();
hw( configure, sensor0, filter, red ); tred = measure();
hw( configure, sensor0, filter, green ); tgreen = measure();
hw( configure, sensor0, filter, blue ); tblue = measure();
if ( tclear < tclear_max &&
tred != 0xFFFF &&
tgreen != 0xFFFF &&
tblue != 0xFFFF ) {
uint32_t tclear256 = 256 * (uint32_t)tclear ;
pred = (tclear256 + tred/2 ) / tred ;
pgreen = (tclear256 + tgreen/2 ) / tgreen ;
pblue = (tclear256 + tblue/2 ) / tblue ;
region_t r ;
for ( rn=0 ; rn<sizeof(ee_regions)/sizeof(region_t) ; rn++ ) {
hw( read_bytes, eeprom0, &r, &ee_regions[rn],
sizeof(r) ) ;
if ( r.radius < 0xFF ) {
uint16_t qp, qr, qg, qb ;
qp = r.radius ;
if (pred > r.red) qr=pred-r.red ; qr=r.red-pred ;
if (pgreen > r.green) qg=pgreen-r.green ; qg=r.green-pgreen ;
if (pblue > r.blue) qb=pblue-r.blue ; qb=r.blue-pblue ;
qp = qp*qp ;
qr = qr*qr ;
qg = qg*qg ;
qb = qb*qb ;
if ( qr+qg+qb < qp )
break ;
}
}
if ( rn < 16 ) {
hw( write, PIN_OUTS, r.id & 0x0F );
}
else {
rn = 0xFF ;
hw( write, PIN_OUTS, 0 );
}
}
else {
rn = 0xFF ;
pred = 0 ;
pgreen = 0 ;
pblue = 0 ;
hw( write, PIN_OUTS, 0 );
}
if (
hw(stat,UART).rxc ) {
uint8_t cmd =
hw( read,UART);
if ( cmd=='s' ) {
if ( tclear != 0xFFFF &&
tred != 0xFFFF &&
tgreen != 0xFFFF &&
tblue != 0xFFFF ) {
tx4h( tclear );
tx4h( tred );
tx4h( tgreen );
tx4h( tblue );
tx2h( pred );
tx2h( pgreen );
tx2h( pblue );
tx2h( rn );
}
else
uart_putbyte( '.');
uart_putbyte( '\n' );
}
else if ( cmd=='r' ) {
for ( uint8_t i=0 ; i<sizeof(ee_regions)/sizeof(region_t) ; i++ ) {
region_t r ;
hw( read_bytes, eeprom0, &r, &ee_regions[i],
sizeof(region_t) );
if ( r.radius != 0xFF ) {
tx2h(i);
tx2h(r.radius);
tx2h(r.red);
tx2h(r.green);
tx2h(r.blue);
tx2h(r.id);
uart_putbyte( '\n');
}
}
}
else if ( cmd=='R' ) {
uart_putbyte( ' ' );
uint8_t cmdbuf[12] ;
uint8_t i=0 ;
for(;;) {
if (
hw(stat,UART).rxc ) {
uint8_t
byte =
hw( read,UART);
if (byte=='\n')
break ;
if ( !ishex(byte) )
i=0xFF ;
if ( i<sizeof(cmdbuf) )
cmdbuf[i++] = byte ;
else
i=0xFF ;
}
}
if ( i!=sizeof(cmdbuf) )
goto error ;
uint8_t rn = HH2i( &cmdbuf[0] );
if ( rn > 15 )
goto error ;
region_t region ;
region.radius = HH2i( &cmdbuf[2] );
region.red = HH2i( &cmdbuf[4] );
region.green = HH2i( &cmdbuf[6] );
region.blue = HH2i( &cmdbuf[8] );
region.id = HH2i( &cmdbuf[10] );
region_t region0 ;
hw( read_bytes, eeprom0, ®ion0, &ee_regions[rn],
sizeof(region) );
if ( __builtin_memcmp(®ion, ®ion0, sizeof(region_t)) )
hw( write_bytes, eeprom0, &ee_regions[rn], ®ion,
sizeof(region) );
uart_putbyte( '\n' );
}
else if ( cmd=='l' ) {
tx4h(tclear_max);
uart_putbyte( '\n' );
}
else if ( cmd=='L' ) {
uart_putbyte( ' ' );
uint8_t cmdbuf[4] ;
uint8_t i=0 ;
for(;;) {
if (
hw(stat,UART).rxc ) {
uint8_t
byte =
hw( read,UART);
if (byte=='\n')
break ;
if ( !ishex(byte) )
i=0xFF ;
if ( i<sizeof(cmdbuf) )
cmdbuf[i++] = byte ;
else
i=0xFF ;
}
}
if ( i!=sizeof(cmdbuf) )
goto error ;
uint16_t max = HHHH2i( &cmdbuf[0] );
if ( max != tclear_max ) {
tclear_max = max ;
hw( write_bytes, eeprom0, &ee_tclear_max, &tclear_max,
sizeof(tclear_max) );
uart_putbyte( 'w' );
}
uart_putbyte( '\n' );
}
else if ( cmd=='\n' )
uart_putbyte( '\n' );
else {
error:
uart_putbyte( '!' );
}
}
}
}