Commit 63d75583 authored by Anders Blomdell's avatar Anders Blomdell
Browse files

Add pcio processes, enhance avr target handling with multiple targets for one project

parent f37894bd
*/avr/compiled
*/linux/compiled
*~
\ No newline at end of file
all:
@echo "###" >&2
@echo "### Atmel AVR targets ###" >&2
@echo "###" >&2
@echo "Do 'make PROCESS.LOAD' or 'make PROCESS.FUSE'" >&2
@echo "where PROCESS is one of" >&2
@for m in */*/Makefile ; do \
echo " $$(dirname $$(dirname $$m))" >&2 \
; done
@./tools/find_avr_targets
@echo "###" >&2
@echo "### Linux targets ###" >&2
@echo "###" >&2
@echo "Do 'make PROGRAM.LINUX'" >&2
@echo "where PROGRAM is one of" >&2
@./tools/find_linux_targets
@echo >&2
@exit 1
%.LOAD:
make -C $*/avr $@
make -C $$(./tools/find_avr_targets $*) $@
%.FUSE:
make -C $*/avr $@
make -C $$(./tools/find_avr_targets $*) $@
%.LINUX:
make -C $$(./tools/find_linux_targets $*) $@
TARGETS=pcio pcio_w_usb
pcio.ARCH=avr
pcio.CHIP=atmega8
# 16 MHz crystal, brown out
pcio.FUSE_L=0x1f
pcio.FUSE_H=0xd9
pcio.C=pcio
pcio.H=../lib/serialio
pcio_w_usb.ARCH=avr
pcio_w_usb.CHIP=atmega16
# 16 MHz crystal, brown out
pcio_w_usb.FUSE_L=0x1f
pcio_w_usb.FUSE_H=0xd9
pcio_w_usb.C=pcio_w_usb
pcio_w_usb.H=../lib/serialio
include ../../lib/avr/Makefile.common
#include <avr/io.h>
#include <avr/interrupt.h>
//#include <avr/signal.h>
#include "serialio.h"
volatile unsigned char error;
volatile unsigned char serial_readbits;
volatile unsigned char serial_readchannels;
volatile unsigned char serial_readconfig;
volatile unsigned int ai0;
volatile unsigned int ai1;
volatile unsigned int ai2;
volatile unsigned int ai3;
SIGNAL(ADC_vect)
{
unsigned char channel = ADMUX & 0x0f;
unsigned int value = ADCW;
switch (channel) {
case 0: {
channel = 1;
ai2 = value;
} break;
case 1: {
channel = 2;
ai3 = value;
} break;
case 2: {
channel = 3;
ai0 = value;
} break;
case 3: {
channel = 0;
ai1 = value;
} break;
default: {
channel = 0;
} break;
}
ADMUX = 0xc0 | channel; // Internal Vref, right adjust
ADCSR = 0xcf; // Enable ADC interrupts, Clock/128
}
typedef enum { cmd_clear_bit, cmd_set_bit,
cmd_read_bit, cmd_read_chan } command;
SIGNAL(USART_RXC_vect)
{
char ch = UDR;
switch (serialio_RXC(ch)) {
case serialio_clearbit: {
switch (serialio_channel) {
// Digital output buffer (ULN2803A) is inverting
case 0: { PORTB = PORTB | 0x01; } break;
case 1: { PORTB = PORTB | 0x10; } break;
case 2: { PORTB = PORTB | 0x20; } break;
case 3: { PORTC = PORTC | 0x10; } break;
case 4: { PORTC = PORTC | 0x20; } break;
case 5: { PORTB = PORTB | 0x08; } break;
}
} break;
case serialio_setbit: {
switch (serialio_channel) {
// Digital output buffer (ULN2803A) is inverting
case 0: { PORTB = PORTB & ~0x01; } break;
case 1: { PORTB = PORTB & ~0x10; } break;
case 2: { PORTB = PORTB & ~0x20; } break;
case 3: { PORTC = PORTC & ~0x10; } break;
case 4: { PORTC = PORTC & ~0x20; } break;
case 5: { PORTB = PORTB & ~0x08; } break;
}
} break;
case serialio_pollbit: {
if (serialio_channel <= 7) {
serial_readbits |= (1<<serialio_channel);
}
} break;
case serialio_pollchannel: {
if (serialio_channel <= 7) {
serial_readchannels |= (1<<serialio_channel);
} else if (serialio_channel == 31) {
serial_readconfig = 1;
}
} break;
case serialio_setchannel: {
switch (serialio_channel) {
case 0: {
OCR1A = serialio_value & 0x3ff;
} break;
case 1: {
OCR1B = serialio_value & 0x3ff;
} break;
} break;
} break;
case serialio_error: {
} break;
case serialio_more: {
} break;
}
}
/*
* PB0 DO5
* PB1 AO0 / DO4
* PB2 AO1 / DO3
* PB3 DO2
* PB4 DO1
* PB5 DO0
*
* PC0 AI2
* PC1 AI3
* PC2 AI0
* PC3 AI1
*
* PD2 DI0
* PD3 DI2
* PD4 DI4
* PD5 DI5
* PD6 DI3
* PD7 DI1
*
*/
int main()
{
serialio_init();
serial_readbits = 0;
serial_readchannels = 0;
serial_readconfig = 0;
ai0 = 0;
ai1 = 0;
ai2 = 0;
ai3 = 0;
PORTD = 0xfc; // PortD, pull up
DDRD = 0x00; // PortD, all input
PORTB = 0x00; // PortB, no pull up
DDRB = 0xff; // PortB, all outputs
PORTC = 0x00; // PortC, no pull up
DDRC = 0x30; // PortC, bit 4 & 5 outputs
TCCR0 = 0x05; // Timer0, Clock / 1024
TCCR1A = 0xa3; // OC1A & OC1B 10 bit PWM (PC), clear on upcounting
TCCR1B = 0x01; // Clock / 1
UCSRA = 0x00; // USART:
UCSRB = 0x98; // USART: RxIntEnable|RxEnable|TxEnable
UCSRC = 0x86; // USART: 8bit, no parity
UBRRH = 0; // USART: 115200 @ 14.7456MHz
UBRRL = 7; // USART: 115200 @ 14.7456MHz
ADMUX = 0xc0; // Internal Vref, right adjust
ADMUX = 0xce; // Internal Vref, right adjust, read 1.22V (Vbg)
ADCSR = 0xcf; // Enable ADC interrupts, Clock/128
SREG = 0x80; // Global interrupt enable
OCR1A = 512 & 0x3ff;
OCR1B = 512 & 0x3ff;
while (1) {
unsigned char bits, channels, config;
SREG = 0x00; // Global interrupt disable
bits = serial_readbits;
serial_readbits = 0;
channels = serial_readchannels;
serial_readchannels = 0;
config = serial_readconfig;
serial_readconfig = 0;
SREG = 0x80; // Global interrupt enable
if (bits & 0x01) { serialio_putbit(0, PIND & 0x04); }
if (bits & 0x02) { serialio_putbit(1, PIND & 0x08); }
if (bits & 0x04) { serialio_putbit(2, PIND & 0x10); }
if (bits & 0x08) { serialio_putbit(3, PIND & 0x20); }
if (bits & 0x10) { serialio_putbit(4, PIND & 0x40); }
if (bits & 0x20) { serialio_putbit(5, PIND & 0x80); }
if (channels & 0x01) { serialio_putchannel(0, 1023 - ai0); }
if (channels & 0x02) { serialio_putchannel(1, 1023 - ai1); }
if (channels & 0x04) { serialio_putchannel(2, 1023 - ai2); }
if (channels & 0x08) { serialio_putchannel(3, 1023 - ai3); }
if (config) {
CONF_DIGITAL_IN(0, CONF_RESOLUTION(1)); // DI0
CONF_DIGITAL_IN(1, CONF_RESOLUTION(1)); // DI1
CONF_DIGITAL_IN(2, CONF_RESOLUTION(1)); // DI2
CONF_DIGITAL_IN(3, CONF_RESOLUTION(1)); // DI3
CONF_DIGITAL_IN(4, CONF_RESOLUTION(1)); // DI4
CONF_DIGITAL_IN(5, CONF_RESOLUTION(1)); // DI5
CONF_DIGITAL_OUT(0, CONF_RESOLUTION(1)); // DO0
CONF_DIGITAL_OUT(1, CONF_RESOLUTION(1)); // DO1
CONF_DIGITAL_OUT(2, CONF_RESOLUTION(1)); // DO2
CONF_DIGITAL_OUT(3, CONF_RESOLUTION(1)); // DO3
CONF_DIGITAL_OUT(4, CONF_RESOLUTION(1)); // DO4
CONF_DIGITAL_OUT(5, CONF_RESOLUTION(1)); // DO5
CONF_ANALOG_IN(0, CONF_RESOLUTION(10)); // AI0
CONF_ANALOG_IN(0, CONF_MIN(CONF_NEGATIVE_MILLIVOLT(10400)));
CONF_ANALOG_IN(0, CONF_MAX(CONF_POSITIVE_MILLIVOLT(10300)));
CONF_ANALOG_IN(1, CONF_RESOLUTION(10)); // AI1
CONF_ANALOG_IN(1, CONF_MIN(CONF_NEGATIVE_MILLIVOLT(10400)));
CONF_ANALOG_IN(1, CONF_MAX(CONF_POSITIVE_MILLIVOLT(10300)));
CONF_ANALOG_IN(2, CONF_RESOLUTION(10)); // AI2
CONF_ANALOG_IN(2, CONF_MIN(CONF_NEGATIVE_MILLIVOLT(10400)));
CONF_ANALOG_IN(2, CONF_MAX(CONF_POSITIVE_MILLIVOLT(10300)));
CONF_ANALOG_IN(3, CONF_RESOLUTION(10)); // AI3
CONF_ANALOG_IN(3, CONF_MIN(CONF_NEGATIVE_MILLIVOLT(10400)));
CONF_ANALOG_IN(3, CONF_MAX(CONF_POSITIVE_MILLIVOLT(10300)));
CONF_ANALOG_OUT(0, CONF_RESOLUTION(10)); // AO0
CONF_ANALOG_OUT(0, CONF_MIN(CONF_NEGATIVE_MILLIVOLT(9800)));
CONF_ANALOG_OUT(0, CONF_MAX(CONF_POSITIVE_MILLIVOLT(10170)));
CONF_ANALOG_OUT(1, CONF_RESOLUTION(10)); // AO1
CONF_ANALOG_OUT(1, CONF_MIN(CONF_NEGATIVE_MILLIVOLT(9800)));
CONF_ANALOG_OUT(1, CONF_MAX(CONF_POSITIVE_MILLIVOLT(10106)));
CONF_END();
}
}
}
#include <avr/io.h>
#include <avr/interrupt.h>
#include "serialio.h"
volatile unsigned char error;
volatile unsigned char serial_readbits;
volatile unsigned char serial_readchannels;
volatile unsigned char serial_readconfig;
volatile unsigned int ai0;
volatile unsigned int ai1;
volatile unsigned int ai2;
volatile unsigned int ai3;
SIGNAL(ADC_vect)
{
unsigned char channel = ADMUX & 0x0f;
unsigned int value = ADCW;
switch (channel) {
case 0: {
channel = 1;
ai0 = value;
} break;
case 1: {
channel = 2;
ai1 = value;
} break;
case 2: {
channel = 3;
ai2 = value;
} break;
case 3: {
channel = 0;
ai3 = value;
} break;
default: {
channel = 0;
} break;
}
ADMUX = 0xc0 | channel; // Internal Vref, right adjust
ADCSRA = 0xcf; // Enable ADC interrupts, Clock/128
}
typedef enum { cmd_clear_bit, cmd_set_bit,
cmd_read_bit, cmd_read_chan } command;
SIGNAL(USART_RXC_vect)
{
char ch = UDR;
switch (serialio_RXC(ch)) {
case serialio_clearbit: {
switch (serialio_channel) {
// Digital output buffer (ULN2803A) is inverting
case 0: { PORTC |= 0x04; } break;
case 1: { PORTC |= 0x08; } break;
case 2: { PORTC |= 0x10; } break;
case 3: { PORTC |= 0x20; } break;
case 4: { PORTC |= 0x40; } break;
case 5: { PORTC |= 0x80; } break;
}
} break;
case serialio_setbit: {
switch (serialio_channel) {
// Digital output buffer (ULN2803A) is inverting
case 0: { PORTC &= ~0x04; } break;
case 1: { PORTC &= ~0x08; } break;
case 2: { PORTC &= ~0x10; } break;
case 3: { PORTC &= ~0x20; } break;
case 4: { PORTC &= ~0x40; } break;
case 5: { PORTC &= ~0x80; } break;
}
} break;
case serialio_pollbit: {
if (serialio_channel <= 7) {
serial_readbits |= (1<<serialio_channel);
}
} break;
case serialio_pollchannel: {
if (serialio_channel <= 7) {
serial_readchannels |= (1<<serialio_channel);
} else if (serialio_channel == 31) {
serial_readconfig = 1;
}
} break;
case serialio_setchannel: {
switch (serialio_channel) {
case 0: {
OCR1B = serialio_value & 0x3ff;
} break;
case 1: {
OCR1A = serialio_value & 0x3ff;
} break;
} break;
} break;
case serialio_error: {
} break;
case serialio_more: {
} break;
}
}
/*
* PA0 AI0
* PA1 AI1
* PA2 AI2
* PA3 AI3
* PA4 DI0
* PA5 DI1
* PA6 DI2
* PA7 DI3
*
* PC2 DO0
* PC3 DO1
* PC4 DO2
* PC5 DO3
* PC6 DO4
* PC7 DO5
*
* PD3 DI5
* PD4 AO0
* PD5 AO1
* PD7 DI4
*
*/
int main()
{
serialio_init();
serial_readbits = 0;
serial_readchannels = 0;
serial_readconfig = 0;
ai0 = 0;
ai1 = 0;
ai2 = 0;
ai3 = 0;
PORTA = 0xf0; // PortA, pull-ups
DDRA = 0x00; // PortA, all inputs
PORTC = 0x00; // PortC, initial data
DDRC = 0xfc; // PortC, 2-7 outputs
PORTD = 0x88; // PortD, pull-ups
DDRD = 0x30; // PortD, 4-5 outputs
TCCR0 = 0x05; // Timer0, Clock / 1024
TCCR1A = 0xa3; // OC1A & OC1B 10 bit PWM (PC), clear on upcounting
TCCR1B = 0x01; // Clock / 1
UCSRA = 0x00; // USART:
UCSRB = 0x98; // USART: RxIntEnable|RxEnable|TxEnable
UCSRC = 0x86; // USART: 8bit, no parity
UBRRH = 0; // USART: 115200 @ 14.7456MHz
UBRRL = 7; // USART: 115200 @ 14.7456MHz
ADMUX = 0xc0; // Internal Vref, right adjust
ADMUX = 0xce; // Internal Vref, right adjust, read 1.22V (Vbg)
ADCSRA = 0xcf; // Enable ADC interrupts, Clock/128
SREG = 0x80; // Global interrupt enable
OCR1A = 512 & 0x3ff;
OCR1B = 512 & 0x3ff;
while (1) {
unsigned char bits, channels, config;
SREG = 0x00; // Global interrupt disable
bits = serial_readbits;
serial_readbits = 0;
channels = serial_readchannels;
serial_readchannels = 0;
config = serial_readconfig;
serial_readconfig = 0;
SREG = 0x80; // Global interrupt enable
if (bits & 0x01) { serialio_putbit(0, PINA & 0x10); }
if (bits & 0x02) { serialio_putbit(1, PINA & 0x20); }
if (bits & 0x04) { serialio_putbit(2, PINA & 0x40); }
if (bits & 0x08) { serialio_putbit(3, PINA & 0x80); }
if (bits & 0x10) { serialio_putbit(4, PIND & 0x80); }
if (bits & 0x20) { serialio_putbit(5, PIND & 0x08); }
if (channels & 0x01) { serialio_putchannel(0, 1023 - ai0); }
if (channels & 0x02) { serialio_putchannel(1, 1023 - ai1); }
if (channels & 0x04) { serialio_putchannel(2, 1023 - ai2); }
if (channels & 0x08) { serialio_putchannel(3, 1023 - ai3); }
if (config) {
CONF_DIGITAL_IN(0, CONF_RESOLUTION(1)); // DI0
CONF_DIGITAL_IN(1, CONF_RESOLUTION(1)); // DI1
CONF_DIGITAL_IN(2, CONF_RESOLUTION(1)); // DI2
CONF_DIGITAL_IN(3, CONF_RESOLUTION(1)); // DI3
CONF_DIGITAL_IN(4, CONF_RESOLUTION(1)); // DI4
CONF_DIGITAL_IN(5, CONF_RESOLUTION(1)); // DI5
CONF_DIGITAL_OUT(0, CONF_RESOLUTION(1)); // DO0
CONF_DIGITAL_OUT(1, CONF_RESOLUTION(1)); // DO1
CONF_DIGITAL_OUT(2, CONF_RESOLUTION(1)); // DO2
CONF_DIGITAL_OUT(3, CONF_RESOLUTION(1)); // DO3
CONF_DIGITAL_OUT(4, CONF_RESOLUTION(1)); // DO4
CONF_DIGITAL_OUT(5, CONF_RESOLUTION(1)); // DO5
CONF_ANALOG_IN(0, CONF_RESOLUTION(10)); // AI0
CONF_ANALOG_IN(0, CONF_MIN(CONF_NEGATIVE_MILLIVOLT(10400)));
CONF_ANALOG_IN(0, CONF_MAX(CONF_POSITIVE_MILLIVOLT(10300)));
CONF_ANALOG_IN(1, CONF_RESOLUTION(10)); // AI1
CONF_ANALOG_IN(1, CONF_MIN(CONF_NEGATIVE_MILLIVOLT(10400)));
CONF_ANALOG_IN(1, CONF_MAX(CONF_POSITIVE_MILLIVOLT(10300)));
CONF_ANALOG_IN(2, CONF_RESOLUTION(10)); // AI2
CONF_ANALOG_IN(2, CONF_MIN(CONF_NEGATIVE_MILLIVOLT(10400)));
CONF_ANALOG_IN(2, CONF_MAX(CONF_POSITIVE_MILLIVOLT(10300)));
CONF_ANALOG_IN(3, CONF_RESOLUTION(10)); // AI3
CONF_ANALOG_IN(3, CONF_MIN(CONF_NEGATIVE_MILLIVOLT(10400)));
CONF_ANALOG_IN(3, CONF_MAX(CONF_POSITIVE_MILLIVOLT(10300)));
CONF_ANALOG_OUT(0, CONF_RESOLUTION(10)); // AO0
CONF_ANALOG_OUT(0, CONF_MIN(CONF_NEGATIVE_MILLIVOLT(9800)));
CONF_ANALOG_OUT(0, CONF_MAX(CONF_POSITIVE_MILLIVOLT(10170)));
CONF_ANALOG_OUT(1, CONF_RESOLUTION(10)); // AO1
CONF_ANALOG_OUT(1, CONF_MIN(CONF_NEGATIVE_MILLIVOLT(9800)));
CONF_ANALOG_OUT(1, CONF_MAX(CONF_POSITIVE_MILLIVOLT(10106)));
CONF_END();
}
}
}
CC=gcc
CFLAGS.pciotest=-Wall -lpthread
.SUFFIXES: .c
all: pciotest.LINUX
.PHONY: %.LINUX
%.LINUX: compiled/% | compiled
@/bin/true
.PRECIOUS: compiled/%
compiled/%: %.c | compiled
echo $*
$(CC) $(CFLAGS.$*) -o $@ $<
compiled:
mkdir -p $@
clean:
rm -rf compiled
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <string.h>
#include <poll.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <signal.h>
static volatile int OK = 1;
static pthread_t reader, writer;
static int digital_in = 0;
static int digital_out = 0;
static int analog_in = 0;
static int analog_out = 0;
static int encoder_in = 0;
static int maxdata_in[32];
static int maxdata_out[32];
static int millivolts(int value) {
int val = value >> 4;
int unit = value & 0x7;
int sign = value & 0x8;
if (sign != 0) { val = -val; }
switch (unit) {
case 0: { val = val * 1000; } break;
case 1: {} break;
case 2: {} break;
}
return val;
}
void *Reader(void *argument) {
int *fd, length, value;
fd = argument;
length = 0;
value = 0;
for (;;) {
unsigned char ch;
if (read(*fd, &ch, 1) <= 0) {
fprintf(stderr, "Read failed\n");
OK = 0;
break;
}
length++;
if ((ch & 0x80) == 0x80) {
value = (value << 7) | (ch & 0x7f);
} else {
unsigned int channel = ch & 0x1f;
value = (value << 2) | ((ch & 0x60) >> 5);
if (length == 1) {
unsigned char cmd = (ch & 0x60) >> 5;
switch (cmd) {
case 0: { // Clear bit
printf("#%d:0 ", channel);
} break;
case 1: { // Set bit
printf("#%d:1 ", channel);
} break;
case 2: { // Read bit
// Currently unused
} break;
case 3: { // Read channel
// Currently unused
} break;
}
} else {
switch (channel) {
case 0:{ printf("I0=%3d ", value); } break;
case 1:{ printf("I1=%3d ", value); } break;
case 2:{ printf("I2=%3d ", value); } break;
case 3:{ printf("I3=%3d ", value); } break;
case 4:{ printf("I4=%3d ", value); } break;
case 5:{ printf("I5=%3d ", value); } break;
case 6:{ printf("I6=%3d ", value); } break;
case 31:{
int kind = (value>>5)& 0x7;
int cmd = (value>>8)& 0x3;
int conf_channel = value & 0x1f;
int *maxdata = 0;
switch(kind) {
case 1: {
printf("digital in ");
digital_in |= 1 << conf_channel;
} break;
case 2: {
printf("digital out ");
digital_out |= 1 << conf_channel;
} break;
case 3: {