--- /dev/null
+// Martin Thomas 4/2008\r
+\r
+#include <stdint.h>\r
+#include <avr/io.h>\r
+#include <util/delay.h>\r
+#include "port_ext.h"\r
+\r
+// #include "mystdio.h"\r
+\r
+static uint8_t virtports[PORT_EXT_OUTPORTS] = { \r
+ PORT_EXT_INIT0, \r
+ PORT_EXT_INIT1, \r
+ PORT_EXT_INIT2 \r
+};\r
+\r
+static inline void strobe_delay(void)\r
+{\r
+#if 0\r
+ // delay ca. 100ns @ 2V for 74x595, 1us for tests \r
+ _delay_us(1);\r
+#else\r
+ // 1 cycle ca 130ns at 7,3MHz\r
+ asm volatile("nop"::);\r
+#endif\r
+}\r
+\r
+static inline void output_disable(void)\r
+{\r
+ PORT_EXT_PORT |= ( 1 << PORT_EXT_PIN_OE );\r
+}\r
+\r
+static inline void output_enable(void)\r
+{\r
+ PORT_EXT_PORT &= ~( 1 << PORT_EXT_PIN_OE );\r
+}\r
+\r
+static inline void pulse_latch(void)\r
+{\r
+ PORT_EXT_PORT |= ( 1 << PORT_EXT_PIN_LATCH );\r
+ strobe_delay();\r
+ PORT_EXT_PORT &= ~( 1 << PORT_EXT_PIN_LATCH );\r
+ strobe_delay();\r
+}\r
+\r
+static inline void pulse_clock(void)\r
+{\r
+ PORT_EXT_PORT |= ( 1 << PORT_EXT_PIN_CLK );\r
+ strobe_delay();\r
+ PORT_EXT_PORT &= ~( 1 << PORT_EXT_PIN_CLK );\r
+ strobe_delay();\r
+}\r
+\r
+static void shift_out(void)\r
+{\r
+ uint8_t i, bit;\r
+\r
+ // first bit shifted out is bit7 in virtports[PORT_EXT_OUTPORTS-1]\r
+ // - on BC100 this is for U205 Q7\r
+ // last bit shifted out is bit 0 in virtports[0]\r
+ // - on BC100 this is for U202 Q0\r
+ for ( i = PORT_EXT_OUTPORTS; i > 0; i-- ) {\r
+ // myprintf_P("Port %d = %d\n", i-1, virtports[i-1] );\r
+ for ( bit = 8; bit > 0; bit-- ) {\r
+ if ( virtports[i-1] & ( 1 << (bit-1) ) ) {\r
+ PORT_EXT_PORT |= ( 1 << PORT_EXT_PIN_DIN );\r
+ }\r
+ else {\r
+ PORT_EXT_PORT &= ~( 1 << PORT_EXT_PIN_DIN );\r
+ }\r
+ pulse_clock();\r
+ }\r
+ }\r
+ pulse_latch();\r
+}\r
+\r
+void port_ext_init(void) \r
+{\r
+ PORT_EXT_PORT &= ~( \r
+ ( 1 << PORT_EXT_PIN_CLK ) |\r
+ ( 1 << PORT_EXT_PIN_DIN) |\r
+ ( 1 << PORT_EXT_PIN_LATCH ) );\r
+ PORT_EXT_PORT |= ( 1 << PORT_EXT_PIN_OE );\r
+ PORT_EXT_DDR |= (\r
+ ( 1 << PORT_EXT_PIN_OE) |\r
+ ( 1 << PORT_EXT_PIN_CLK ) |\r
+ ( 1 << PORT_EXT_PIN_DIN) |\r
+ ( 1 << PORT_EXT_PIN_LATCH ) );\r
+ // set inititial values before enabling outputs\r
+ // - on BC100 this is just for U202 since it's\r
+ // the only 74x595 with switchable /OE\r
+ shift_out();\r
+ output_enable();\r
+ // since Q7' is low while output is disabled (low)\r
+ // (Philips 74HC(T)595 datasheet) another shift- \r
+ // out has to be done to set the cascaded outputs\r
+ // - on BC100 this will set U201, U202 and U205 outputs\r
+ shift_out();\r
+}\r
+\r
+void port_ext_update(void)\r
+{\r
+ shift_out();\r
+}\r
+\r
+void port_ext_bit_clear( uint8_t port, uint8_t bit )\r
+{\r
+ if ( ( port < PORT_EXT_OUTPORTS ) && ( bit < 8 ) ) {\r
+ virtports[port] &= ~( 1 << bit );\r
+ }\r
+}\r
+\r
+void port_ext_bit_set( uint8_t port, uint8_t bit )\r
+{\r
+ if ( ( port < PORT_EXT_OUTPORTS ) && ( bit < 8 ) ) {\r
+ virtports[port] |= ( 1 << bit );\r
+ }\r
+}\r
+\r
+void port_ext_set( uint8_t port, uint8_t val )\r
+{\r
+ if ( port < PORT_EXT_OUTPORTS ) {\r
+ virtports[port] = val;\r
+ }\r
+}\r
+\r
+\r