4008-04-07 Release
[avr_bc100.git] / BaseMegaFirmware / GCC / port_ext.c
1 // Martin Thomas 4/2008\r
2 \r
3 #include <stdint.h>\r
4 #include <avr/io.h>\r
5 #include <util/delay.h>\r
6 #include "port_ext.h"\r
7 \r
8 // #include "mystdio.h"\r
9 \r
10 static uint8_t virtports[PORT_EXT_OUTPORTS] = { \r
11         PORT_EXT_INIT0, \r
12         PORT_EXT_INIT1, \r
13         PORT_EXT_INIT2 \r
14 };\r
15 \r
16 static inline void strobe_delay(void)\r
17 {\r
18 #if 0\r
19         // delay ca. 100ns @ 2V for 74x595, 1us for tests \r
20         _delay_us(1);\r
21 #else\r
22         // 1 cycle ca 130ns at 7,3MHz\r
23         asm volatile("nop"::);\r
24 #endif\r
25 }\r
26 \r
27 static inline void output_disable(void)\r
28 {\r
29         PORT_EXT_PORT |= ( 1 << PORT_EXT_PIN_OE );\r
30 }\r
31 \r
32 static inline void output_enable(void)\r
33 {\r
34         PORT_EXT_PORT &= ~( 1 << PORT_EXT_PIN_OE );\r
35 }\r
36 \r
37 static inline void pulse_latch(void)\r
38 {\r
39         PORT_EXT_PORT |= ( 1 << PORT_EXT_PIN_LATCH );\r
40         strobe_delay();\r
41         PORT_EXT_PORT &= ~( 1 << PORT_EXT_PIN_LATCH );\r
42         strobe_delay();\r
43 }\r
44 \r
45 static inline void pulse_clock(void)\r
46 {\r
47         PORT_EXT_PORT |= ( 1 << PORT_EXT_PIN_CLK );\r
48         strobe_delay();\r
49         PORT_EXT_PORT &= ~( 1 << PORT_EXT_PIN_CLK );\r
50         strobe_delay();\r
51 }\r
52 \r
53 static void shift_out(void)\r
54 {\r
55         uint8_t i, bit;\r
56 \r
57         // first bit shifted out is bit7 in virtports[PORT_EXT_OUTPORTS-1]\r
58         // - on BC100 this is for U205 Q7\r
59         // last bit shifted out is bit 0 in virtports[0]\r
60         // - on BC100 this is for U202 Q0\r
61         for ( i = PORT_EXT_OUTPORTS; i > 0; i-- ) {\r
62                 // myprintf_P("Port %d = %d\n", i-1, virtports[i-1] );\r
63                 for ( bit = 8; bit > 0; bit-- ) {\r
64                         if ( virtports[i-1] & ( 1 << (bit-1) ) ) {\r
65                                 PORT_EXT_PORT |= ( 1 << PORT_EXT_PIN_DIN );\r
66                         }\r
67                         else {\r
68                                 PORT_EXT_PORT &= ~( 1 << PORT_EXT_PIN_DIN );\r
69                         }\r
70                         pulse_clock();\r
71                 }\r
72         }\r
73         pulse_latch();\r
74 }\r
75 \r
76 void port_ext_init(void) \r
77 {\r
78         PORT_EXT_PORT &= ~( \r
79                 ( 1 << PORT_EXT_PIN_CLK ) |\r
80                 ( 1 << PORT_EXT_PIN_DIN)  |\r
81                 ( 1 << PORT_EXT_PIN_LATCH ) );\r
82         PORT_EXT_PORT |= ( 1 << PORT_EXT_PIN_OE );\r
83         PORT_EXT_DDR  |= (\r
84                 ( 1 << PORT_EXT_PIN_OE)   |\r
85                 ( 1 << PORT_EXT_PIN_CLK ) |\r
86                 ( 1 << PORT_EXT_PIN_DIN)  |\r
87                 ( 1 << PORT_EXT_PIN_LATCH ) );\r
88         // set inititial values before enabling outputs\r
89         // - on BC100 this is just for U202 since it's\r
90         //   the only 74x595 with switchable /OE\r
91         shift_out();\r
92         output_enable();\r
93         // since Q7' is low while output is disabled (low)\r
94         // (Philips 74HC(T)595 datasheet) another shift- \r
95         // out has to be done to set the cascaded outputs\r
96         // - on BC100 this will set U201, U202 and U205 outputs\r
97         shift_out();\r
98 }\r
99 \r
100 void port_ext_update(void)\r
101 {\r
102         shift_out();\r
103 }\r
104 \r
105 void port_ext_bit_clear( uint8_t port, uint8_t bit )\r
106 {\r
107         if ( ( port < PORT_EXT_OUTPORTS ) && ( bit < 8 ) ) {\r
108                 virtports[port] &= ~( 1 << bit );\r
109         }\r
110 }\r
111 \r
112 void port_ext_bit_set( uint8_t port, uint8_t bit )\r
113 {\r
114         if ( ( port < PORT_EXT_OUTPORTS ) && ( bit < 8 ) ) {\r
115                 virtports[port] |= ( 1 << bit );\r
116         }\r
117 }\r
118 \r
119 void port_ext_set( uint8_t port, uint8_t val )\r
120 {\r
121         if ( port < PORT_EXT_OUTPORTS ) {\r
122                 virtports[port] = val;\r
123         }\r
124 }\r
125 \r
126 \r