implement menu on LCD
Stefan Schuermans

Stefan Schuermans commited on 2012-04-04 22:26:27
Showing 5 changed files, with 271 additions and 53 deletions.

... ...
@@ -1,48 +1,16 @@
1 1
 #include "arp.h"
2 2
 #include "cyc_cnt.h"
3
+#include "dhcp.h"
3 4
 #include "eth.h"
4 5
 #include "ip.h"
5
-#include "lcd.h"
6 6
 #include "leds.h"
7
-#include "switches.h"
7
+#include "menu.h"
8 8
 #include "uart.h"
9 9
 #include "udp.h"
10 10
 
11 11
 unsigned char leds_val = 0x88;
12 12
 
13
-void uint2digits(unsigned int uint, unsigned int cnt, char digits[])
14
-{
15
-  while (cnt > 0) {
16
-    --cnt;
17
-    digits[cnt] = '0' + uint % 10;
18
-    uint /= 10;
19
-  }
20
-}
21
-
22
-void switches(void)
23
-{
24
-  char cnt_digits[4];
25
-
26
-  lcd_chr(1, 0, switches_get_state(sw_0) ? '0' : ' ');
27
-  lcd_chr(1, 1, switches_get_state(sw_1) ? '1' : ' ');
28
-  lcd_chr(1, 2, switches_get_state(sw_2) ? '2' : ' ');
29
-  lcd_chr(1, 3, switches_get_state(sw_3) ? '3' : ' ');
30
-  lcd_chr(1, 4, switches_get_state(sw_east) ? 'E' : ' ');
31
-  lcd_chr(1, 5, switches_get_state(sw_north) ? 'N' : ' ');
32
-  lcd_chr(1, 6, switches_get_state(sw_south) ? 'S' : ' ');
33
-  lcd_chr(1, 7, switches_get_state(sw_west) ? 'W' : ' ');
34
-  lcd_chr(1, 8, switches_get_state(sw_center) ? 'C' : ' ');
35
-  lcd_chr(1, 9, switches_get_state(sw_rot_a) ? 'a' : ' ');
36
-  lcd_chr(1, 10, switches_get_state(sw_rot_b) ? 'b' : ' ');
37
-
38
-  uint2digits(switches_get_rot_cnt(), 4, cnt_digits);
39
-  lcd_chr(1, 12, cnt_digits[0]);
40
-  lcd_chr(1, 13, cnt_digits[1]);
41
-  lcd_chr(1, 14, cnt_digits[2]);
42
-  lcd_chr(1, 15, cnt_digits[3]);
43
-}
44
-
45
-void uart(void)
13
+void uart_rx_task(void)
46 14
 {
47 15
   unsigned short chr;
48 16
 
... ...
@@ -53,28 +21,20 @@ void uart(void)
53 21
   }
54 22
 }
55 23
 
56
-void eth_task(void)
24
+void eth_rx_task(void)
57 25
 {
58 26
   void *vptr;
59 27
   unsigned int sz;
60
-  char digits[2];
61 28
 
62 29
   while (eth_rx(&vptr, &sz))
63 30
     ethernet_recv(vptr, sz);
64
-
65
-  uint2digits(eth_rx_get_cnt(), 2, digits);;
66
-  lcd_chr(0, 11, digits[0]);
67
-  lcd_chr(0, 12, digits[1]);
68
-  uint2digits(eth_tx_get_cnt(), 2, digits);;
69
-  lcd_chr(0, 14, digits[0]);
70
-  lcd_chr(0, 15, digits[1]);
71 31
 }
72 32
 
73 33
 void tasks(void)
74 34
 {
75
-  switches();
76
-  uart();
77
-  eth_task();
35
+  uart_rx_task();
36
+  eth_rx_task();
37
+  menu_task();
78 38
 }
79 39
 
80 40
 void leds_tick200(void)
... ...
@@ -89,6 +49,7 @@ void tick200(void)
89 49
   arp_tick200();
90 50
   ip_tick200();
91 51
   udp_tick200();
52
+  dhcp_tick200();
92 53
 }
93 54
 
94 55
 int main()
... ...
@@ -97,15 +58,13 @@ int main()
97 58
 
98 59
   leds_set_state(0x01);
99 60
 
100
-  eth_mac_init();
101
-  eth_rx_init();
102
-  eth_tx_init();
61
+  menu_init();
103 62
 
104 63
   leds_set_state(0x02);
105 64
 
106
-  lcd_init();
107
-  lcd_str(0, "MIPS I");
108
-  lcd_str(1, "");
65
+  eth_mac_init();
66
+  eth_rx_init();
67
+  eth_tx_init();
109 68
 
110 69
   leds_set_state(0x04);
111 70
 
... ...
@@ -34,3 +34,39 @@ void memcpy(void *dest, const void *src, unsigned int sz)
34 34
     *dest1++ = *src1++;
35 35
 }
36 36
 
37
+/**
38
+ * @brief set memory to fixed value
39
+ * @param[in] dest pointer to destination buffer
40
+ * @param[in] val fixed value to fill memory with
41
+ * @param[in] sz size of memory to fill
42
+ */
43
+void memset(void *dest, int val, unsigned int sz)
44
+{
45
+  unsigned char val1;
46
+  unsigned int *dest4;
47
+  unsigned int val4;
48
+  unsigned int sz4;
49
+  unsigned char *dest1;
50
+
51
+  val1 = val;
52
+
53
+  // word aligned memory address -> fast fill
54
+  if (((unsigned int)dest & 3) == 0) {
55
+    dest4 = dest;
56
+    val4 = val1;
57
+    val4 |= val4 << 8;
58
+    val4 |= val4 << 16;
59
+    sz4 = sz >> 2;
60
+    for ( ; sz4 > 0; --sz4)
61
+      *dest4++ = val4;
62
+    // there might still be a few bytes to fill now
63
+    dest = dest4;
64
+    sz &= 3;
65
+  }
66
+
67
+  // safe and slow fallback: fill byte-wise
68
+  dest1 = dest;
69
+  for ( ; sz > 0; --sz)
70
+    *dest1++ = val1;
71
+}
72
+
... ...
@@ -9,5 +9,13 @@
9 9
  */
10 10
 void memcpy(void *dest, const void *src, unsigned int sz);
11 11
 
12
+/**
13
+ * @brief set memory to fixed value
14
+ * @param[in] dest pointer to destination buffer
15
+ * @param[in] val fixed value to fill memory with
16
+ * @param[in] sz size of memory to fill
17
+ */
18
+void memset(void *dest, int val, unsigned int sz);
19
+
12 20
 #endif // #ifdef MEMCPY_H
13 21
 
... ...
@@ -0,0 +1,204 @@
1
+#include "config.h"
2
+#include "eth.h"
3
+#include "lcd.h"
4
+#include "macros.h"
5
+#include "menu.h"
6
+#include "switches.h"
7
+
8
+/// last value of rotary knob
9
+static unsigned int menu_cur_rot_val = 0;
10
+
11
+/// current screen
12
+static int menu_cur_screen = 0;
13
+
14
+/// current content on screen
15
+static char menu_cur_content[16];
16
+
17
+/**
18
+ * @brief convert unsigned integer to decimal
19
+ * @param[in] uint unsigned integer value
20
+ * @param[in] cnt number of digits
21
+ * @param[out] digits value as decimal digits
22
+ */
23
+void menu_uint2dec(unsigned int uint, unsigned int cnt, char digits[])
24
+{
25
+  while (cnt > 0) {
26
+    --cnt;
27
+    digits[cnt] = '0' + uint % 10;
28
+    uint /= 10;
29
+  }
30
+}
31
+
32
+/**
33
+ * @brief convert unsigned integer to hexadecimal
34
+ * @param[in] uint unsigned integer value
35
+ * @param[in] cnt number of digits
36
+ * @param[out] digits value as decimal hexadigits
37
+ */
38
+void menu_uint2hex(unsigned int uint, unsigned int cnt, char digits[])
39
+{
40
+  unsigned int val;
41
+
42
+  while (cnt > 0) {
43
+    --cnt;
44
+    val = uint & 15;
45
+    digits[cnt] = val < 10 ? '0' + val : 'A' - 10 + val;
46
+    uint >>= 4;
47
+  }
48
+}
49
+
50
+/**
51
+ * @brief update screen content
52
+ * @param[in] str new content to display
53
+ */
54
+static void menu_update_content(const char *str)
55
+{
56
+  unsigned int i;
57
+
58
+  // update only characters that changed (LCD is slow)
59
+  for (i = 0; str[i] != 0 && i < 16; ++i) {
60
+    if (menu_cur_content[i] != str[i]) {
61
+      menu_cur_content[i] = str[i];
62
+      lcd_chr(1, i, str[i]);
63
+    }
64
+  }
65
+  // clear rest of line
66
+  for (; i < 16; ++i) {
67
+    if (menu_cur_content[i] != ' ') {
68
+      menu_cur_content[i] = ' ';
69
+      lcd_chr(1, i, ' ');
70
+    }
71
+  }
72
+}
73
+
74
+/// start screen
75
+static void menu_screen_start(void)
76
+{
77
+  menu_update_content("turn knob...");
78
+}
79
+
80
+/// switches screen
81
+static void menu_screen_switches(void)
82
+{
83
+  char buf[11];
84
+
85
+  buf[0] = switches_get_state(sw_0) ? '0' : ' ';
86
+  buf[1] = switches_get_state(sw_1) ? '1' : ' ';
87
+  buf[2] = switches_get_state(sw_2) ? '2' : ' ';
88
+  buf[3] = switches_get_state(sw_3) ? '3' : ' ';
89
+  buf[4] = switches_get_state(sw_east) ? 'E' : ' ';
90
+  buf[5] = switches_get_state(sw_north) ? 'N' : ' ';
91
+  buf[6] = switches_get_state(sw_south) ? 'S' : ' ';
92
+  buf[7] = switches_get_state(sw_west) ? 'W' : ' ';
93
+  buf[8] = switches_get_state(sw_center) ? 'C' : ' ';
94
+  buf[9] = switches_get_state(sw_rot_a) ? 'a' : ' ';
95
+  buf[10] = switches_get_state(sw_rot_b) ? 'b' : ' ';
96
+  buf[11] = 0;
97
+
98
+  menu_update_content(buf);
99
+}
100
+
101
+/// ethernet screen
102
+static void menu_screen_eth(void)
103
+{
104
+  char buf[] = "RX 0000 TX 0000";
105
+
106
+  menu_uint2dec(eth_rx_get_cnt(), 4, &buf[3]);
107
+  menu_uint2dec(eth_tx_get_cnt(), 4, &buf[11]);
108
+
109
+  menu_update_content(buf);
110
+}
111
+
112
+/// MAC address screen
113
+static void menu_screen_mac(void)
114
+{
115
+  unsigned int i;
116
+  char buf[] = "000000000000";
117
+
118
+  for (i = 0; i < 6; ++i)
119
+    menu_uint2hex(config_mac.mac[i], 2, &buf[i * 2]);
120
+
121
+  menu_update_content(buf);
122
+}
123
+
124
+/// IP address screen
125
+static void menu_screen_ip(void)
126
+{
127
+  unsigned int i;
128
+  char buf[] = "000.000.000.000";
129
+
130
+  for (i = 0; i < 4; ++i)
131
+    menu_uint2dec(config_ip.ip[i], 3, &buf[i * 4]);
132
+
133
+  menu_update_content(buf);
134
+}
135
+
136
+/// subnet mask screen
137
+static void menu_screen_netmask(void)
138
+{
139
+  unsigned int i;
140
+  char buf[] = "000.000.000.000";
141
+
142
+  for (i = 0; i < 4; ++i)
143
+    menu_uint2dec(config_ip.mask[i], 3, &buf[i * 4]);
144
+
145
+  menu_update_content(buf);
146
+}
147
+
148
+/// gateway IP screen
149
+static void menu_screen_gateway(void)
150
+{
151
+  unsigned int i;
152
+  char buf[] = "000.000.000.000";
153
+
154
+  for (i = 0; i < 4; ++i)
155
+    menu_uint2dec(config_ip.gw[i], 3, &buf[i * 4]);
156
+
157
+  menu_update_content(buf);
158
+}
159
+
160
+/// available screens
161
+static struct menu_screen {
162
+  const char *title; ///< title of screen
163
+  void (*update)(void); ///< function to update screen content
164
+} menu_screens[] = {
165
+  { "MIPS I", menu_screen_start },
166
+  { "switches", menu_screen_switches },
167
+  { "ethernet", menu_screen_eth },
168
+  { "MAC address", menu_screen_mac },
169
+  { "IP address", menu_screen_ip },
170
+  { "subnet mask", menu_screen_netmask },
171
+  { "gateway IP", menu_screen_gateway },
172
+};
173
+
174
+/// initialize
175
+void menu_init(void)
176
+{
177
+  lcd_init();
178
+  menu_cur_screen = 0;
179
+  lcd_str(0, menu_screens[0].title);
180
+  menu_screens[0].update();
181
+}
182
+
183
+/// task procedure - call as often as possible
184
+void menu_task(void)
185
+{
186
+  // get new screen to show
187
+  unsigned int new_rot_cnt = switches_get_rot_cnt();
188
+  unsigned int new_rot_val = (new_rot_cnt + 2) / 4; // 1 click is 4 steps
189
+  int delta = new_rot_val - menu_cur_rot_val;
190
+  menu_cur_rot_val = new_rot_val;
191
+  int new_screen = menu_cur_screen + delta;
192
+  if (new_screen < 0)
193
+    new_screen = count(menu_screens) - (-new_screen % count(menu_screens));
194
+  new_screen = new_screen % count(menu_screens);
195
+
196
+  // screen changed -> show new title
197
+  if (new_screen != menu_cur_screen) {
198
+    menu_cur_screen = new_screen;
199
+    lcd_str(0, menu_screens[menu_cur_screen].title);
200
+  }
201
+  // update current screen
202
+  menu_screens[menu_cur_screen].update();
203
+}
204
+
... ...
@@ -0,0 +1,11 @@
1
+#ifndef MENU_H
2
+#define MENU_H
3
+
4
+/// initialize
5
+void menu_init(void);
6
+
7
+/// task procedure - call as often as possible
8
+void menu_task(void);
9
+
10
+#endif // #ifdef MENU_H
11
+
0 12