LMS 2012
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
d_ui.c
Go to the documentation of this file.
1 /*
2  * LEGO® MINDSTORMS EV3
3  *
4  * Copyright (C) 2010-2013 The LEGO Group
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  */
20 
21 
33 #ifndef PCASM
34 #include <asm/types.h>
35 #endif
36 
37 #define HW_ID_SUPPORT
38 
39 #include "../../lms2012/source/lms2012.h"
40 #include "../../lms2012/source/am1808.h"
41 
42 
43 #define MODULE_NAME "ui_module"
44 #define DEVICE1_NAME UI_DEVICE
45 
46 static int ModuleInit(void);
47 static void ModuleExit(void);
48 
49 #include <linux/kernel.h>
50 #include <linux/fs.h>
51 
52 #include <linux/sched.h>
53 
54 #ifndef PCASM
55 #include <linux/mm.h>
56 #include <linux/hrtimer.h>
57 
58 #include <linux/init.h>
59 #include <linux/uaccess.h>
60 #include <linux/debugfs.h>
61 
62 #include <linux/ioport.h>
63 #include <asm/gpio.h>
64 #include <asm/io.h>
65 #include <linux/module.h>
66 #include <linux/miscdevice.h>
67 #include <asm/uaccess.h>
68 
69 MODULE_LICENSE("GPL");
70 MODULE_AUTHOR("The LEGO Group");
73 
74 module_init(ModuleInit);
75 module_exit(ModuleExit);
76 
77 #else
78 // Keep Eclipse happy
79 #endif
80 
81 #ifdef DEBUG_D_UI
82 #define DEBUG
83 #endif
84 
85 int Hw = 0;
86 
88 {
96 };
97 
99 {
100  BUT0, // UP
101  BUT1, // ENTER
102  BUT2, // DOWN
103  BUT3, // RIGHT
104  BUT4, // LEFT
105  BUT5, // BACK
107 };
108 
109 
111 
113 
114 
115 #define NO_OF_LEDS LEDS
116 #define NO_OF_BUTTONS BUTTONS
117 
125 INPIN EP2_UiLedPin[LED_PINS] =
126 {
127  { GP6_12, NULL, 0 }, // DIODE1
128  { GP6_14, NULL, 0 }, // DIODE2
129  { GP6_13, NULL, 0 }, // DIODE3
130  { GP6_7 , NULL, 0 }, // DIODE0
131 };
132 
133 INPIN EP2_UiButPin[BUT_PINS] =
134 {
135  { GP7_15, NULL, 0 }, // BUT0
136  { GP1_13, NULL, 0 }, // BUT1
137  { GP7_14, NULL, 0 }, // BUT2
138  { GP7_12, NULL, 0 }, // BUT3
139  { GP6_6 , NULL, 0 }, // BUT4
140  { GP6_10, NULL, 0 }, // BUT5
141 };
142 
143 
144 INPIN FINALB_UiLedPin[LED_PINS] =
145 {
146  { GP6_12, NULL, 0 }, // DIODE1
147  { GP2_1 , NULL, 0 }, // DIODE2
148  { GP6_13, NULL, 0 }, // DIODE3
149  { GP6_7 , NULL, 0 }, // DIODE0
150 };
151 
152 INPIN FINALB_UiButPin[BUT_PINS] =
153 {
154  { GP7_15, NULL, 0 }, // BUT0
155  { GP0_1 , NULL, 0 }, // BUT1
156  { GP7_14, NULL, 0 }, // BUT2
157  { GP7_12, NULL, 0 }, // BUT3
158  { GP6_6 , NULL, 0 }, // BUT4
159  { GP6_10, NULL, 0 }, // BUT5
160 };
161 
162 
163 INPIN FINAL_UiLedPin[LED_PINS] =
164 {
165  { GP6_7 , NULL, 0 }, // DIODE0
166  { GP6_13, NULL, 0 }, // DIODE1
167  { GP2_1 , NULL, 0 }, // DIODE2
168  { GP5_7 , NULL, 0 }, // DIODE3
169 };
170 
171 INPIN FINAL_UiButPin[BUT_PINS] =
172 {
173  { GP7_15, NULL, 0 }, // BUT0
174  { GP0_1 , NULL, 0 }, // BUT1
175  { GP7_14, NULL, 0 }, // BUT2
176  { GP7_12, NULL, 0 }, // BUT3
177  { GP6_6 , NULL, 0 }, // BUT4
178  { GP6_10, NULL, 0 }, // BUT5
179 };
180 
181 /* \endverbatim
182  * \n
183  */
184 
185 
187 {
188  [FINAL] = FINAL_UiLedPin, // FINAL platform
189  [FINALB] = FINALB_UiLedPin, // FINALB platform
190  [EP2] = EP2_UiLedPin, // EP2 platform
191 };
192 
193 
195 {
196  [FINAL] = FINAL_UiButPin, // FINAL platform
197  [FINALB] = FINALB_UiButPin, // FINALB platform
198  [EP2] = EP2_UiButPin, // EP2 platform
199 };
200 
201 
202 //*****************************************************************************
203 
204 
205 static void __iomem *GpioBase;
206 
207 void SetGpio(int Pin)
208 {
209  int Tmp = 0;
210  void __iomem *Reg;
211 
212  if (Pin >= 0)
213  {
214  while ((MuxRegMap[Tmp].Pin != -1) && (MuxRegMap[Tmp].Pin != Pin))
215  {
216  Tmp++;
217  }
218  if (MuxRegMap[Tmp].Pin == Pin)
219  {
220  Reg = da8xx_syscfg0_base + 0x120 + (MuxRegMap[Tmp].MuxReg << 2);
221 
222  *(u32*)Reg &= MuxRegMap[Tmp].Mask;
223  *(u32*)Reg |= MuxRegMap[Tmp].Mode;
224 
225  #ifdef DEBUG
226  printk(" GP%d_%-2d 0x%08X and 0x%08X or 0x%08X\n",(Pin >> 4),(Pin & 0x0F),(u32)Reg, MuxRegMap[Tmp].Mask, MuxRegMap[Tmp].Mode);
227  #endif
228 
229  }
230  else
231  {
232  printk("* GP%d_%-2d ********* ERROR not found *********\n",(Pin >> 4),(Pin & 0x0F));
233  }
234  }
235 }
236 
237 
238 void InitGpio(void)
239 {
240  int Pin;
241 
242  // unlock
243  REGUnlock;
244 
245 #ifdef DEBUG
246  printk(" Ui leds\n");
247 #endif
248  memcpy(UiLedPin,pUiLedPin[Hw],sizeof(EP2_UiLedPin));
249  if (memcmp((const void*)UiLedPin,(const void*)pUiLedPin[Hw],sizeof(EP2_UiLedPin)) != 0)
250  {
251  printk("%s UiLedPin tabel broken!\n",MODULE_NAME);
252  }
253 
254  for (Pin = 0;Pin < NO_OF_LEDS;Pin++)
255  {
256  if (UiLedPin[Pin].Pin >= 0)
257  {
258  UiLedPin[Pin].pGpio = (struct gpio_controller *__iomem)(GpioBase + ((UiLedPin[Pin].Pin >> 5) * 0x28) + 0x10);
259  UiLedPin[Pin].Mask = (1 << (UiLedPin[Pin].Pin & 0x1F));
260 
261  SetGpio(UiLedPin[Pin].Pin);
262  }
263  }
264 
265 #ifdef DEBUG
266  printk(" Ui buttons\n");
267 #endif
268  memcpy(UiButPin,pUiButPin[Hw],sizeof(EP2_UiButPin));
269  if (memcmp((const void*)UiButPin,(const void*)pUiButPin[Hw],sizeof(EP2_UiButPin)) != 0)
270  {
271  printk("%s UiButPin tabel broken!\n",MODULE_NAME);
272  }
273 
274  for (Pin = 0;Pin < NO_OF_BUTTONS;Pin++)
275  {
276  if (UiButPin[Pin].Pin >= 0)
277  {
278  UiButPin[Pin].pGpio = (struct gpio_controller *__iomem)(GpioBase + ((UiButPin[Pin].Pin >> 5) * 0x28) + 0x10);
279  UiButPin[Pin].Mask = (1 << (UiButPin[Pin].Pin & 0x1F));
280 
281  SetGpio(UiButPin[Pin].Pin);
282  }
283  }
284 
285  // lock
286  REGLock;
287 }
288 
289 
290 
291 // DEVICE1 ********************************************************************
292 
293 static struct hrtimer Device1Timer;
294 static ktime_t Device1Time;
295 static struct hrtimer Device2Timer;
296 static ktime_t Device2Time;
297 
298 static UI UiDefault;
299 static UI *pUi = &UiDefault;
300 
301 #define BUTFloat(B) {\
302  (*UiButPin[B].pGpio).dir |= UiButPin[B].Mask;\
303  }
304 
305 
306 #define BUTRead(B) ((*UiButPin[B].pGpio).in_data & UiButPin[B].Mask)
307 
308 
309 #define DIODEInit(D) {\
310  (*UiLedPin[D].pGpio).clr_data = UiLedPin[D].Mask;\
311  (*UiLedPin[D].pGpio).dir &= ~UiLedPin[D].Mask;\
312  }
313 
314 #define DIODEOn(D) {\
315  (*UiLedPin[D].pGpio).set_data = UiLedPin[D].Mask;\
316  }
317 
318 #define DIODEOff(D) {\
319  (*UiLedPin[D].pGpio).clr_data = UiLedPin[D].Mask;\
320  }
321 
322 
323 ULONG LEDPATTERNDATA[NO_OF_LEDS + 1][LEDPATTERNS] =
324 { // LED_BLACK LED_GREEN LED_RED LED_ORANGE LED_GREEN_FLASH LED_RED_FLASH LED_ORANGE_FLASH LED_GREEN_PULSE LED_RED_PULSE LED_ORANGE_PULSE
325  { 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0b00000000000000000000000000000000, 0b00000000000000000111110000011111, 0b00000000000000000111110000011111, 0b00000000000000000000000000000000, 0b00000000000000000000000001110111, 0b00000000000000000000000001110111 }, // RR
326  { 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0b00000000000000000111110000011111, 0b00000000000000000000000000000000, 0b00000000000000000111110000011111, 0b00000000000000000000000001110111, 0b00000000000000000000000000000000, 0b00000000000000000000000001110111 }, // RG
327  { 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0b00000000000000000000000000000000, 0b00000000000000000111110000011111, 0b00000000000000000111110000011111, 0b00000000000000000000000000000000, 0b00000000000000000000000001110111, 0b00000000000000000000000001110111 }, // LR
328  { 0x00000000, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0b00000000000000000111110000011111, 0b00000000000000000000000000000000, 0b00000000000000000111110000011111, 0b00000000000000000000000001110111, 0b00000000000000000000000000000000, 0b00000000000000000000000001110111 }, // LG
329  { 0 }
330 };
331 
332 
333 UBYTE PatternBlock = 0; // Block pattern update
334 UBYTE PatternBits = 20; // Pattern bits
335 UBYTE PatternBit = 0; // Pattern bit pointer
338 
339 static enum hrtimer_restart Device1TimerInterrupt1(struct hrtimer *pTimer)
340 {
341  UBYTE Tmp;
342 
343  if (PatternBlock)
344  {
345  PatternBlock = 0;
346  }
347  else
348  {
349  for (Tmp = 0;Tmp < NO_OF_LEDS;Tmp++)
350  {
351  if (PatternBit == 0)
352  {
353  TmpPattern[Tmp] = ActPattern[Tmp];
354  }
355  if ((TmpPattern[Tmp] & 0x00000001))
356  {
357  DIODEOn(Tmp);
358  }
359  else
360  {
361  DIODEOff(Tmp);
362  }
363  TmpPattern[Tmp] >>= 1;
364  }
365 
366  if (++PatternBit >= PatternBits)
367  {
368  PatternBit = 0;
369  }
370  }
371 
372  // restart timer
373  hrtimer_forward_now(pTimer,ktime_set(0,50000000));
374 
375  return (HRTIMER_RESTART);
376 }
377 
378 
379 static enum hrtimer_restart Device2TimerInterrupt1(struct hrtimer *pTimer)
380 {
381  UWORD Tmp;
382 
383  for(Tmp = 0;Tmp < BUT_PINS;Tmp++)
384  {
385  if (BUTRead(Tmp))
386  { // Button active
387 
388  (*pUi).Pressed[Tmp] = 1;
389 
390  }
391  else
392  { // Button inactive
393 
394  (*pUi).Pressed[Tmp] = 0;
395 
396  }
397  }
398 
399  // restart timer
400  hrtimer_forward_now(pTimer,ktime_set(0,10000000));
401 
402  return (HRTIMER_RESTART);
403 }
404 
405 
435 static ssize_t Device1Write(struct file *File,const char *Buffer,size_t Count,loff_t *Data)
436 {
437  char Buf[2];
438  UBYTE No;
439  UBYTE Tmp;
440  int Lng = 0;
441 
442  if (Count >= 2)
443  {
444  Lng = Count;
445  copy_from_user(Buf,Buffer,2);
446  No = Buf[0] - '0';
447  if ((No >= 0) && (No < LEDPATTERNS))
448  {
449  PatternBlock = 1;
450 
451  PatternBits = 20;
452  PatternBit = 0;
453 
454  for (Tmp = 0;Tmp < NO_OF_LEDS;Tmp++)
455  {
456  ActPattern[Tmp] = LEDPATTERNDATA[Tmp][No];
457  }
458 
459  PatternBlock = 0;
460  }
461  }
462 
463  return (Lng);
464 }
465 
466 
467 static ssize_t Device1Read(struct file *File,char *Buffer,size_t Count,loff_t *Offset)
468 {
469  int Lng = 0;
470 
471  Lng = snprintf(Buffer,Count,"V%c.%c0",HwId[0],HwId[1]);
472 
473  return (Lng);
474 }
475 
476 
477 #define SHM_LENGTH (sizeof(UiDefault))
478 #define NPAGES ((SHM_LENGTH + PAGE_SIZE - 1) / PAGE_SIZE)
479 static void *kmalloc_ptr;
480 
481 static int Device1Mmap(struct file *filp, struct vm_area_struct *vma)
482 {
483  int ret;
484 
485  ret = remap_pfn_range(vma,vma->vm_start,virt_to_phys((void*)((unsigned long)pUi)) >> PAGE_SHIFT,vma->vm_end-vma->vm_start,PAGE_SHARED);
486 
487  if (ret != 0)
488  {
489  ret = -EAGAIN;
490  }
491 
492  return (ret);
493 }
494 
495 
496 static const struct file_operations Device1Entries =
497 {
498  .owner = THIS_MODULE,
499  .read = Device1Read,
500  .write = Device1Write,
501  .mmap = Device1Mmap
502 };
503 
504 
505 static struct miscdevice Device1 =
506 {
507  MISC_DYNAMIC_MINOR,
508  DEVICE1_NAME,
509  &Device1Entries
510 };
511 
512 static int Device1Init(void)
513 {
514  int Result = -1;
515  int Tmp;
516  int i;
517  UWORD *pTmp;
518 
519  Result = misc_register(&Device1);
520  if (Result)
521  {
522  printk(" %s device register failed\n",DEVICE1_NAME);
523  }
524  else
525  {
526  // allocate kernel shared memory for ui button states (pUi)
527  if ((kmalloc_ptr = kmalloc((NPAGES + 2) * PAGE_SIZE, GFP_KERNEL)) != NULL)
528  {
529  pTmp = (UWORD*)((((unsigned long)kmalloc_ptr) + PAGE_SIZE - 1) & PAGE_MASK);
530  for (i = 0; i < NPAGES * PAGE_SIZE; i += PAGE_SIZE)
531  {
532  SetPageReserved(virt_to_page(((unsigned long)pTmp) + i));
533  }
534  pUi = (UI*)pTmp;
535  memset(pUi,0,sizeof(UI));
536 
537  for (Tmp = 0;Tmp < NO_OF_LEDS;Tmp++)
538  {
539  DIODEInit(Tmp);
540  }
541  for (Tmp = 0;Tmp < NO_OF_BUTTONS;Tmp++)
542  {
543  BUTFloat(Tmp);
544  }
545 
546  // setup ui update timer interrupt
547  Device2Time = ktime_set(0,10000000);
548  hrtimer_init(&Device2Timer,CLOCK_MONOTONIC,HRTIMER_MODE_REL);
549  Device2Timer.function = Device2TimerInterrupt1;
550  hrtimer_start(&Device2Timer,Device2Time,HRTIMER_MODE_REL);
551 
552  // setup ui update timer interrupt
553  Device1Time = ktime_set(0,50000000);
554  hrtimer_init(&Device1Timer,CLOCK_MONOTONIC,HRTIMER_MODE_REL);
555  Device1Timer.function = Device1TimerInterrupt1;
556  hrtimer_start(&Device1Timer,Device1Time,HRTIMER_MODE_REL);
557 
558 #ifdef DEBUG
559  printk(" %s device register succes\n",DEVICE1_NAME);
560 #endif
561  }
562  }
563 
564  return (Result);
565 }
566 
567 
568 static void Device1Exit(void)
569 {
570  int Tmp;
571  int i;
572  UWORD *pTmp;
573 
574  hrtimer_cancel(&Device1Timer);
575  hrtimer_cancel(&Device2Timer);
576 
577  for (Tmp = 0;Tmp < NO_OF_LEDS;Tmp++)
578  {
579  DIODEOff(Tmp);
580  }
581 
582  // free shared memory
583  pTmp = (UWORD*)pUi;
584  pUi = &UiDefault;
585 
586  for (i = 0; i < NPAGES * PAGE_SIZE; i+= PAGE_SIZE)
587  {
588  ClearPageReserved(virt_to_page(((unsigned long)pTmp) + i));
589 #ifdef DEBUG
590  printk(" %s memory page %d unmapped\n",DEVICE1_NAME,i);
591 #endif
592  }
593  kfree(kmalloc_ptr);
594 
595  misc_deregister(&Device1);
596 #ifdef DEBUG
597  printk(" %s device unregistered\n",DEVICE1_NAME);
598 #endif
599 }
600 
601 
602 // MODULE *********************************************************************
603 
604 
605 #ifndef PCASM
606 module_param (HwId, charp, 0);
607 #endif
608 
609 static int ModuleInit(void)
610 {
611  Hw = HWID;
612 
613  if (Hw < PLATFORM_START)
614  {
615  Hw = PLATFORM_START;
616  }
617  if (Hw > PLATFORM_END)
618  {
619  Hw = PLATFORM_END;
620  }
621 
622 #ifdef DEBUG
623  printk("%s init started\n",MODULE_NAME);
624 #endif
625 
626  if (request_mem_region(DA8XX_GPIO_BASE,0xD8,MODULE_NAME) >= 0)
627  {
628  GpioBase = (void*)ioremap(DA8XX_GPIO_BASE,0xD8);
629  if (GpioBase != NULL)
630  {
631 #ifdef DEBUG
632  printk("%s gpio address mapped\n",MODULE_NAME);
633 #endif
634 
635  InitGpio();
636 
637  Device1Init();
638  }
639  }
640 
641  return (0);
642 }
643 
644 
645 static void ModuleExit(void)
646 {
647 #ifdef DEBUG
648  printk("%s exit started\n",MODULE_NAME);
649 #endif
650 
651  Device1Exit();
652  iounmap(GpioBase);
653 
654 }
Definition: d_ui.c:93
INPIN UiLedPin[LED_PINS]
Definition: d_ui.c:110
#define REGLock
Definition: am1808.h:235
MODULE_AUTHOR("The LEGO Group")
#define snprintf
Definition: c_input.c:141
Definition: am1808.h:39
Definition: d_ui.c:102
INPIN * pUiLedPin[]
Definition: d_ui.c:186
ULONG TmpPattern[NO_OF_LEDS]
Definition: d_ui.c:337
Definition: am1808.h:35
MRM MuxRegMap[]
Definition: am1808.h:59
MODULE_LICENSE("GPL")
#define DIODEOff(D)
Definition: d_ui.c:318
GPIOC pGpio
Definition: am1808.h:225
#define REGUnlock
Definition: am1808.h:230
UBYTE PatternBlock
Definition: d_ui.c:333
#define DIODEOn(D)
Definition: d_ui.c:314
Definition: am1808.h:33
Definition: am1808.h:222
module_init(ModuleInit)
#define EP2
Schematics revision D.
Definition: lms2012.h:99
Definition: d_ui.c:89
INPIN UiButPin[BUT_PINS]
Definition: d_ui.c:112
Definition: d_ui.c:104
#define FINAL
Final prototype.
Definition: lms2012.h:101
Definition: d_ui.c:106
int Hw
Definition: d_ui.c:85
Definition: am1808.h:39
void InitGpio(void)
Definition: d_ui.c:238
Definition: d_ui.c:95
ULONG LEDPATTERNDATA[NO_OF_LEDS+1][LEDPATTERNS]
Definition: d_ui.c:323
u16 MuxReg
Definition: am1808.h:53
#define NO_OF_LEDS
Definition: d_ui.c:115
unsigned int ULONG
Basic Type used to symbolise 32 bit unsigned values.
Definition: lmstypes.h:31
Definition: d_ui.c:90
#define DEVICE1_NAME
Definition: d_ui.c:44
#define DIODEInit(D)
Definition: d_ui.c:309
Definition: d_ui.c:100
Definition: d_ui.c:103
UiButPins
Definition: d_ui.c:98
UBYTE PatternBit
Definition: d_ui.c:335
ULONG ActPattern[NO_OF_LEDS]
Definition: d_ui.c:336
int Pin
Definition: am1808.h:224
Definition: d_ui.c:91
#define NO_OF_BUTTONS
Definition: d_ui.c:116
#define FINALB
Schematics revision B and C.
Definition: lms2012.h:100
Definition: am1808.h:40
Definition: am1808.h:39
Definition: am1808.h:39
Definition: d_ui.c:92
Definition: am1808.h:40
unsigned char UBYTE
Basic Type used to symbolise 8 bit unsigned values.
Definition: lmstypes.h:29
MODULE_SUPPORTED_DEVICE(DEVICE1_NAME)
u32 Mask
Definition: am1808.h:226
void SetGpio(int Pin)
Definition: d_ui.c:207
#define NPAGES
Definition: d_ui.c:478
unsigned short UWORD
Basic Type used to symbolise 16 bit unsigned values.
Definition: lmstypes.h:30
char Buffer[1024]
Definition: c_wifi.c:102
INPIN * pUiButPin[]
Definition: d_ui.c:194
UBYTE PatternBits
Definition: d_ui.c:334
Definition: am1808.h:34
module_param(HwId, charp, 0)
MODULE_DESCRIPTION(MODULE_NAME)
module_exit(ModuleExit)
UiLedPins
Definition: d_ui.c:87
Definition: am1808.h:39
Definition: d_ui.c:105
Definition: d_ui.c:101
uint32_t u32
Definition: common.h:158
#define BUTRead(B)
Definition: d_ui.c:306
Definition: am1808.h:39
Definition: d_ui.c:94
#define MODULE_NAME
Definition: d_ui.c:43
#define PLATFORM_END
Newest supported hardware (newer versions will use this)
Definition: lms2012.h:105
Definition: am1808.h:40
#define BUTFloat(B)
Definition: d_ui.c:301
Definition: am1808.h:38
#define PLATFORM_START
Oldest supported hardware (older versions will use this)
Definition: lms2012.h:104
#define NULL