4008-04-07 Release
[avr_bc100.git] / BaseMegaFirmware / GCC / port_ext.c
diff --git a/BaseMegaFirmware/GCC/port_ext.c b/BaseMegaFirmware/GCC/port_ext.c
new file mode 100644 (file)
index 0000000..40ff4ab
--- /dev/null
@@ -0,0 +1,126 @@
+// 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