// // ATP.XMEGA.E.h // ATP XMEGA E header // // Neil Gershenfeld // 12/13/15 // // (c) Massachusetts Institute of Technology 2015 // This work may be reproduced, modified, distributed, // performed, and displayed for any purpose. Copyright is // retained and must be preserved. The work is provided // as is; no warranty is provided, and users accept all // liability. // /* logical states T(oken) B(it) 00 x empty 01 o occupied 10 0 0 11 1 1 send handshake x -- x 0,1 -> x 0,1 <- o x -> o x <- x receive handshake x -- x x <- 0,1 o -> 0,1 o <- x x -> x send/receive signals send receive O x11xx xxoox TO _--__ _____ BO _--__ __--_ TI _____ _--__ BI __--_ _--__ I xxoox x11xx swap handshake x -- x 0,1 -> x 0,1 <- 0,1 o -> 0,1 o <- o x -> o x <- x simultaneous swap handshake x -- x 0,1 <> 0,1 o <> o x <> x missed simultaneous swap handshake x -- x 0,1 <> 0,1 o <> x x -> x port states out out in in 00 00 x x empty 00 01 x o send acknowledge 00 10 x 0 receive available 00 11 x 1 receive available 01 00 o x receive acknowledge 01 01 o o swap accept 01 10 o 0 receive accept 01 11 o 1 receive accept 10 00 0 x send available 10 01 0 o send accept 10 10 0 0 swap available 10 11 0 1 swap available 11 00 1 x send available 11 01 1 o send accept 11 10 1 0 swap available 11 11 1 1 swap available */ // // includes // #include #include // // virtual ports // #define VPORTA VPORT0 // pre-mapped virtual port A #define VPORTC VPORT1 // pre-mapped virtual port C #define VPORTD VPORT2 // pre-mapped virtual port D #define VPORTR VPORT3 // pre-mapped virtual port R // // logical states // T(oken) // B(it) #define ATP_x 0b00 #define ATP_o 0b01 #define ATP_0 0b10 #define ATP_1 0b11 // // port states // out out // in in #define ATP_xx 0b0000 #define ATP_xo 0b0001 #define ATP_x0 0b0010 #define ATP_x1 0b0011 #define ATP_ox 0b0100 #define ATP_oo 0b0101 #define ATP_o0 0b0110 #define ATP_o1 0b0111 #define ATP_0x 0b1000 #define ATP_0o 0b1001 #define ATP_00 0b1010 #define ATP_01 0b1011 #define ATP_1x 0b1100 #define ATP_1o 0b1101 #define ATP_10 0b1110 #define ATP_11 0b1111 // // ATP port type // typedef struct { unsigned char number; VPORT_t *vport; unsigned char bi; // bit in pin unsigned char bo; // bit out pin unsigned char ti; // token in pin unsigned char to; // token out pin unsigned char mask; // pin bit mask unsigned char size; // byte buffer size struct { struct { unsigned char value; unsigned char count; } bit; struct { unsigned char value; unsigned char count; } byte; } in; // input port struct { struct { unsigned char value; unsigned char count; } bit; struct { unsigned char value; unsigned char count; } byte; } out; // output port } ATP_port; // // macros // #define set(port,pin) (port |= pin) // set port pin #define clear(port,pin) (port &= (~pin)) // clear port pin // // ATP_init // initialize ATP data structure // #define ATP_init(name,number,bufsize)\ static ATP_port name[number]; {\ unsigned char i;\ for (i = 0; i < number; ++i)\ name[i].size = bufsize;\ } // // ATP_setup // set up ATP port // #define ATP_setup(name,id,letter,bipin,tipin,bopin,topin)\ name[id].vport = &VPORT ## letter;\ name[id].bi = (1 << bipin);\ name[id].ti = (1 << tipin);\ name[id].bo = (1 << bopin);\ name[id].to = (1 << topin);\ name[id].in.byte.value = 0;\ name[id].in.byte.count = 0;\ name[id].out.byte.value = 0;\ name[id].out.byte.count = 0;\ name[id].mask = (1<OUT &= ~name[id].bo;\ name[id].vport->OUT &= ~name[id].to;\ name[id].vport->DIR |= name[id].bo;\ name[id].vport->DIR |= name[id].to;\ PORT ## letter.PIN ## bipin ## CTRL = PORT_OPC_PULLDOWN_gc;\ PORT ## letter.PIN ## tipin ## CTRL = PORT_OPC_PULLDOWN_gc; // // ATP_input // read state from ATP port // #define ATP_input(ports,id) ({\ static unsigned char in;\ in = ports[id].vport->IN;\ (((in & ports[id].bi)?0b0001:0)|((in & ports[id].ti)?0b0010:0)|((in & ports[id].bo)?0b0100:0)|((in & ports[id].to)?0b1000:0));\ }) // // ATP_output // write state to ATP port // #define ATP_output(ports,id,state) {\ switch (state) {\ case ATP_x:\ ports[id].vport->OUT = (ports[id].vport->OUT & ~ports[id].mask) | 0;\ break;\ case ATP_o:\ ports[id].vport->OUT = (ports[id].vport->OUT & ~ports[id].mask) | (ports[id].bo);\ break;\ case ATP_0:\ ports[id].vport->OUT = (ports[id].vport->OUT & ~ports[id].mask) | (ports[id].to);\ break;\ case ATP_1:\ ports[id].vport->OUT = (ports[id].vport->OUT & ~ports[id].mask) | (ports[id].to|ports[id].bo);\ break;\ }\ } // // ATP_put_bit_out // put ATP bit out // #define ATP_put_bit_out(ports,id) {\ if (ports[id].out.bit.count == 1) {\ if (ports[id].out.bit.value == 0) {\ ATP_output(ports,id,ATP_0);}\ else {\ ATP_output(ports,id,ATP_1);}\ }\ } // // ATP_accept_bit_out // accept ATP bit out // #define ATP_accept_bit_out(ports,id) {\ ports[id].out.bit.count = 0;\ ATP_process_bit_out(ports,id);\ } // // ATP_get_bit_in // get ATP bit in // #define ATP_get_bit_in(ports,id,bitvalue) {\ ports[id].in.bit.value = bitvalue;\ } // // ATP_accept_bit_in // accept ATP bit in // #define ATP_accept_bit_in(ports,id) {\ ports[id].in.bit.count = 1;\ ATP_process_bit_in(ports,id);\ } // // ATP_push_bit_out // push ATP bit out // #define ATP_push_bit_out(ports,id,bitvalue) {\ ports[id].out.bit.value = bitvalue;\ ports[id].out.bit.count = 1;\ } // // ATP_pop_bit_in // pop ATP bit in // #define ATP_pop_bit_in(ports,id) {\ ports[id].in.bit.value = 0;\ ports[id].in.bit.count = 0;\ } // // ATP_push_byte_out // push ATP byte out // #define ATP_push_byte_out(ports,id,bytevalue) {\ ports[id].out.bit.value = (bytevalue >> 7) & 1;\ ports[id].out.bit.count = 1;\ ports[id].out.byte.value = bytevalue;\ ports[id].out.byte.count = 7;\ } // // ATP_pop_byte_in // pop ATP byte in // #define ATP_pop_byte_in(ports,id) {\ ports[id].in.byte.value = 0;\ ports[id].in.byte.count = 0;\ } // // ATP_push_bit_byte_in // push bit on ATP byte in #define ATP_push_bit_byte_in(ports,id) {\ ports[id].in.byte.value = (ports[id].in.byte.value << 1) | ports[id].in.bit.value;\ ports[id].in.byte.count += 1;\ } // // ATP_pop_bit_byte_out // pop bit on ATP byte out // #define ATP_pop_bit_byte_out(ports,id) {\ if (ports[id].out.byte.count > 0) {\ ports[id].out.byte.count -= 1;\ ports[id].out.bit.value = (ports[id].out.byte.value >> ports[id].out.byte.count) & 1;\ ports[id].out.bit.count = 1;\ }\ } // // ATP_check_state // check for ATP state // #define ATP_check_state(ports,id,state) {\ if (ATP_input(ports,id) != state) {\ break;\ }\ } // // ATP_scan // scan port // #define ATP_scan(ports,id) {\ switch (ATP_input(ports,id)) {\ case ATP_xx:\ ATP_check_state(ports,id,ATP_xx);\ ATP_put_bit_out(ports,id);\ break;\ case ATP_0o:\ ATP_check_state(ports,id,ATP_0o);\ ATP_output(ports,id,ATP_x);\ ATP_accept_bit_out(ports,id);\ break;\ case ATP_1o:\ ATP_check_state(ports,id,ATP_1o);\ ATP_output(ports,id,ATP_x);\ ATP_accept_bit_out(ports,id);\ break;\ case ATP_x0:\ ATP_check_state(ports,id,ATP_x0);\ ATP_output(ports,id,ATP_o);\ ATP_get_bit_in(ports,id,0);\ break;\ case ATP_x1:\ ATP_check_state(ports,id,ATP_x1);\ ATP_output(ports,id,ATP_o);\ ATP_get_bit_in(ports,id,1);\ break;\ case ATP_ox:\ ATP_check_state(ports,id,ATP_ox);\ ATP_output(ports,id,ATP_x);\ ATP_accept_bit_in(ports,id);\ break;\ case ATP_00:\ ATP_check_state(ports,id,ATP_00);\ ATP_output(ports,id,ATP_o);\ ATP_get_bit_in(ports,id,0);\ break;\ case ATP_01:\ ATP_check_state(ports,id,ATP_01);\ ATP_output(ports,id,ATP_o);\ ATP_get_bit_in(ports,id,1);\ break;\ case ATP_10:\ ATP_check_state(ports,id,ATP_10);\ ATP_output(ports,id,ATP_o);\ ATP_get_bit_in(ports,id,0);\ break;\ case ATP_11:\ ATP_check_state(ports,id,ATP_11);\ ATP_output(ports,id,ATP_o);\ ATP_get_bit_in(ports,id,1);\ break;\ case ATP_oo:\ ATP_check_state(ports,id,ATP_oo);\ ATP_output(ports,id,ATP_x);\ ATP_accept_bit_out(ports,id);\ ATP_accept_bit_in(ports,id);\ break;\ }\ }