20080319 release: CV support
[avr_serial_lcd.git] / serial_lcd.c
index 0c8bb10aa85dd36c288d89cb41e623a00e9a65bb..1235c7ba0c527653ba7284c3a149a9c977940bd5 100644 (file)
@@ -11,8 +11,9 @@
 **\r
 ** Compilers supported:\r
 **   - WinAVR-20071221 (includes avr-libc 1.6 required for proper _delay_us)\r
-**   - IAR AVR 4.30\r
-**   - Imagecraft AVR 7\r
+**   - IAR AVR 4.30 and 5.10\r
+**   - Imagecraft AVR 7.16\r
+**   - Codevision AVR 2.02.06\r
 **\r
 ** LICENSE\r
 **   See accompaning LICENSE file\r
@@ -30,7 +31,7 @@ FUSES = {
   .extended = EFUSE_DEFAULT,\r
 };\r
 #endif\r
-\r
+  \r
 // Number of PWM brightness levels supported\r
 #define LED_BRIGHTNESS_LEVELS 8\r
 \r
@@ -93,6 +94,12 @@ static FLASH_DECLARE(const unsigned char ledPwmPatterns[]) =
 #pragma global_register ledPwmCount:20 sUartRxHead:21 sUartRxTail:22 ledPwmCycling:23\r
 unsigned char ledPwmCount, sUartRxHead, sUartRxTail, ledPwmCycling;\r
 \r
+#elif defined(__CODEVISIONAVR__)\r
+#pragma regalloc-\r
+register unsigned char ledPwmCount, sUartRxHead, sUartRxTail, ledPwmCycling;\r
+#pragma regalloc+\r
+\r
+// Use avr_compat register variables\r
 #else\r
 REGISTER_VAR(unsigned char ledPwmCount, "r4", 15);\r
 REGISTER_VAR(unsigned char sUartRxHead, "r5", 14);\r
@@ -101,8 +108,16 @@ REGISTER_VAR(unsigned char ledPwmCycling, "r7", 12);
 #endif\r
 \r
 #define ledPwmPattern GPIOR0\r
-#define ledStatus GPIOR1\r
+#if defined(REGISTER_BIT)\r
 #define BIT_led_on REGISTER_BIT(GPIOR1,0)\r
+#define BACKLIGHT_STATUS() BIT_led_on\r
+#define BACKLIGHT_OFF() BIT_led_on = 0\r
+#define BACKLIGHT_ON() BIT_led_on = 1\r
+#else\r
+#define BACKLIGHT_STATUS() (GPIOR1 & 0x01)\r
+#define BACKLIGHT_OFF() GPIOR1 &=~ ~0x01\r
+#define BACKLIGHT_ON() GPIOR1 |= 0x01\r
+#endif\r
 \r
 // Function declarations\r
 void LcdWriteCmd (unsigned char);\r
@@ -110,8 +125,8 @@ void LcdWriteData (unsigned char);
 unsigned char LcdBusyWait (void);\r
 static unsigned char WaitRxChar (void);\r
 \r
-// ImageCraft doesn't support inline functions, so use preprocessor\r
-#if defined(__IMAGECRAFT__)\r
+// ImageCraft/Codevision don't support inline functions, so use preprocessor\r
+#if defined(__IMAGECRAFT__) || defined(__CODEVISIONAVR__)\r
 #define LedTimerStop() TCCR0B = 0\r
 // Start with 256 prescaler\r
 #define LedTimerStart() TCCR0B = (1<<CS02)\r
@@ -139,7 +154,7 @@ static inline void LedPwmInit (void) {
   TIMSK = (1<<OCIE0A);  // Turn on timer0 COMPA intr (all other timer intr off)\r
   LED_PORT &= ~(1<<LED_PIN); // Ensure LED is off during initialization\r
   LED_DIR |= (1<<LED_PIN);   // Ensure LED is output direction\r
-  BIT_led_on = 0;       // note that LED is off\r
+  BACKLIGHT_OFF();       // note that LED is off\r
   ledPwmPattern = 0xFF; // maximum brightness\r
 }\r
 \r
@@ -149,7 +164,7 @@ static inline void LedPwmSetBrightness (unsigned char brightness) {
   unsigned char ledPwmPos;\r
 \r
   if (brightness == 0) { // turn backlight off for 0 brightness\r
-    if (BIT_led_on) {\r
+    if (BACKLIGHT_STATUS()) {\r
       LedTimerStop();\r
       ledPwmPattern = 0;\r
       ledPwmCycling = 0;\r
@@ -158,7 +173,7 @@ static inline void LedPwmSetBrightness (unsigned char brightness) {
     return;\r
   }\r
 \r
-  ledPwmPos = (brightness * (LED_BRIGHTNESS_LEVELS-1) + 127) >> 8;\r
+  ledPwmPos = (brightness * (LED_BRIGHTNESS_LEVELS-1) + (unsigned int) 127) >> 8;\r
   // Below is probably not required, but ensures we don't exceed array\r
   if (ledPwmPos > LED_BRIGHTNESS_LEVELS - 1)\r
     ledPwmPos = LED_BRIGHTNESS_LEVELS - 1;\r
@@ -168,12 +183,12 @@ static inline void LedPwmSetBrightness (unsigned char brightness) {
   ledPwmCycling = ledPwmPattern;\r
   if (ledPwmPos >= LED_BRIGHTNESS_LEVELS-1) { // maximum brightness\r
     // don't need PWM for continuously on\r
-    if (BIT_led_on) {\r
+    if (BACKLIGHT_STATUS()) {\r
       LedTimerStop();\r
       LED_PORT |= (1<<LED_PIN);\r
     }\r
   } else {\r
-    if (BIT_led_on) {\r
+    if (BACKLIGHT_STATUS()) {\r
       LedTimerStart();\r
     }\r
   }\r
@@ -182,13 +197,13 @@ static inline void LedPwmSetBrightness (unsigned char brightness) {
 INLINE_FUNC_DECLARE(static void LedPwmSwitchOff (void));\r
 static inline void LedPwmSwitchOff (void) {\r
   LED_PORT &= ~(1<<LED_PIN);\r
-  BIT_led_on = 0;\r
+  BACKLIGHT_OFF();\r
   LedTimerStop();\r
 }\r
 \r
 INLINE_FUNC_DECLARE(static void LedPwmSwitchOn (void));\r
 static inline void LedPwmSwitchOn (void) {\r
-  BIT_led_on = 1;\r
+  BACKLIGHT_ON();\r
   if (ledPwmPattern == 0xFF) { // maximum brightness, no need for PWM\r
     LedTimerStop();\r
     LED_PORT |= (1<<LED_PIN); // keep LED on at all times\r
@@ -248,13 +263,17 @@ static inline void UsartInit(void) {
 #endif\r
 }\r
 \r
-#if defined(__IMAGECRAFT__)\r
+#if defined(__IMAGECRAFT__) || defined(__CODEVISIONAVR__)\r
 // Clock cycle = 67nS @ 14.7456MHz\r
 // Delay resolution ~ 1uS @ 14.7456MHz\r
 // So this function is only accurate at near above frequency\r
 void _delay_us (unsigned int d) {\r
   while (d-- != 0);\r
+#if defined(__IMAGECRAFT__)\r
   asm("nop");\r
+#elif defined(__CODEVISIONAVR__)\r
+  #asm("nop")\r
+#endif\r
 }\r
 #endif\r
 \r
@@ -293,7 +312,11 @@ static inline void LcdInit (void) {
 MAIN_FUNC() {\r
   MCUSR = 0; // clear all reset flags\r
 \r
-  wdt_reset();\r
+#if defined(__CODEVISIONAVR__)\r
+      #asm("wdr");\r
+#else\r
+      wdt_reset();\r
+#endif\r
   WDTCSR |= (1<<WDCE)|(1<<WDE); // start timed sequence (keep old prescaler)\r
   WDTCSR = (1<<WDE)|(1<<WDP3)|(1<<WDP0); // 1024K cycles, 8.0sec\r
   MCUCR &= ~((1<<SM1)|(1<<SM0)); // use idle sleep mode\r
@@ -304,7 +327,11 @@ MAIN_FUNC() {
   // Initialize the AVR USART\r
   UsartInit ();\r
 \r
+#if defined(__CODEVISIONAVR__)\r
+      #asm("sei");\r
+#else\r
   sei();\r
+#endif\r
   while (1) {\r
     unsigned char tail = sUartRxTail; // explicitly set order of volatile access\r
     if (tail != sUartRxHead) { // Check if UART RX buffer has a character\r
@@ -327,22 +354,50 @@ MAIN_FUNC() {
     } else {\r
       // No characters waiting in RX buffer\r
 \r
+#if defined(__CODEVISIONAVR__)\r
+      #asm("cli");\r
+#else\r
       cli();\r
+#endif\r
+#if defined(__CODEVISIONAVR__)\r
+      #asm("wdr");\r
+#else\r
       wdt_reset();\r
+#endif\r
       MCUSR &= ~(1<<WDRF); // clear any watchdog interrupt flags\r
       WDTCSR |= (1<<WDCE)|(1<<WDE); // start timed sequence (keep old prescaler)\r
       WDTCSR &= ~(1<<WDE); // watchdog timer off\r
+#if defined(__CODEVISIONAVR__)\r
+      #asm("sei");\r
+#else\r
       sei();\r
+#endif\r
 \r
       sleep_enable();\r
+#if defined(__CODEVISIONAVR__)\r
+      #asm("sleep");\r
+#else\r
       sleep_cpu();\r
+#endif\r
       sleep_disable();\r
 \r
+#if defined(__CODEVISIONAVR__)\r
+      #asm("cli");\r
+#else\r
       cli();\r
+#endif\r
+#if defined(__CODEVISIONAVR__)\r
+      #asm("wdr");\r
+#else\r
       wdt_reset();\r
+#endif\r
       WDTCSR |= (1<<WDCE)|(1<<WDE); // start timed sequence (keep old prescaler)\r
       WDTCSR &= ~(1<<WDCE);\r
+#if defined(__CODEVISIONAVR__)\r
+      #asm("sei");\r
+#else\r
       sei();\r
+#endif\r
     }\r
   }\r
   MAIN_FUNC_LAST();\r
@@ -351,11 +406,36 @@ MAIN_FUNC() {
 void LcdWriteCmd (unsigned char Cmd) {\r
   LcdBusyWait();\r
   LCD_DATA_PORT = Cmd;  // BusyWait leaves RS low in "Register mode"\r
-  NOP();\r
+#if defined(__CODEVISIONAVR__)\r
+  #asm("nop");\r
+#else\r
+   NOP();\r
+#endif\r
   LCD_CONTROL_PORT |= (1<<LCD_E);\r
+#if defined(__CODEVISIONAVR__)\r
+  #if CONSERVATIVE_ENABLE_DURATION\r
+    #asm("nop")\r
+    #asm("nop")\r
+    #asm("nop")\r
+    #asm("nop")\r
+    #asm("nop")\r
+    #asm("nop")\r
+    #asm("nop")\r
+  #else\r
+    #asm("nop")\r
+    #asm("nop")\r
+    #asm("nop")\r
+    #asm("nop")\r
+  #endif\r
+#else\r
   ENABLE_WAIT();\r
+#endif\r
   LCD_CONTROL_PORT &= ~(1<<LCD_E);\r
-  NOP();\r
+#if defined(__CODEVISIONAVR__)\r
+  #asm("nop");\r
+#else\r
+   NOP();\r
+#endif\r
   LCD_CONTROL_PORT |= (1<<LCD_RS); // Set display to "Character mode"\r
 }\r
 \r
@@ -363,9 +443,30 @@ void LcdWriteData (unsigned char c) {
   LcdBusyWait();\r
   LCD_CONTROL_PORT |= (1<<LCD_RS); // Set display to "Character Mode"\r
   LCD_DATA_PORT = c;\r
-  NOP();\r
+#if defined(__CODEVISIONAVR__)\r
+  #asm("nop");\r
+#else\r
+   NOP();\r
+#endif\r
   LCD_CONTROL_PORT |= (1<<LCD_E);\r
+#if defined(__CODEVISIONAVR__)\r
+  #if CONSERVATIVE_ENABLE_DURATION\r
+    #asm("nop")\r
+    #asm("nop")\r
+    #asm("nop")\r
+    #asm("nop")\r
+    #asm("nop")\r
+    #asm("nop")\r
+    #asm("nop")\r
+  #else\r
+    #asm("nop")\r
+    #asm("nop")\r
+    #asm("nop")\r
+    #asm("nop")\r
+  #endif\r
+#else\r
   ENABLE_WAIT();\r
+#endif\r
   LCD_CONTROL_PORT &= ~(1<<LCD_E);\r
 }\r
 \r
@@ -374,11 +475,36 @@ unsigned char LcdBusyWait (void) {
   LCD_DATA_DIR = 0x00; // Set LCD data port to inputs\r
   LCD_CONTROL_PORT &= ~(1<<LCD_RS); // Set display to "Register mode"\r
   LCD_CONTROL_PORT |= (1<<LCD_RW); // Put the display in the read mode\r
-  NOP();\r
+#if defined(__CODEVISIONAVR__)\r
+  #asm("nop");\r
+#else\r
+   NOP();\r
+#endif\r
   do {\r
-    wdt_reset();\r
+#if defined(__CODEVISIONAVR__)\r
+      #asm("wdr");\r
+#else\r
+      wdt_reset();\r
+#endif\r
     LCD_CONTROL_PORT |= (1<<LCD_E);\r
-    ENABLE_WAIT();\r
+#if defined(__CODEVISIONAVR__)\r
+  #if CONSERVATIVE_ENABLE_DURATION\r
+    #asm("nop")\r
+    #asm("nop")\r
+    #asm("nop")\r
+    #asm("nop")\r
+    #asm("nop")\r
+    #asm("nop")\r
+    #asm("nop")\r
+  #else\r
+    #asm("nop")\r
+    #asm("nop")\r
+    #asm("nop")\r
+    #asm("nop")\r
+  #endif\r
+#else\r
+  ENABLE_WAIT();\r
+#endif\r
     LCDStatus = LCD_DATA_PIN_REG;\r
     LCD_CONTROL_PORT &= ~(1<<LCD_E);\r
   } while (LCDStatus & (1<<LCD_BUSY));\r
@@ -427,14 +553,22 @@ static unsigned char WaitRxChar (void) {
   unsigned char tail;\r
   do {\r
     tail = sUartRxTail; // explicitly set order of volatile variable access\r
-    wdt_reset();\r
+#if defined(__CODEVISIONAVR__)\r
+      #asm("wdr");\r
+#else\r
+      wdt_reset();\r
+#endif\r
   } while (sUartRxHead == tail); // while buffer is empty\r
 \r
 #if USE_CTS\r
   // turn off interrupts so that if UART char ready to be stored, then storage\r
   // will occur after CTS pin is set active. This allows UART ISR to set\r
   //  CTS inactive if byte fills buffer after we remove current byte\r
+#if defined(__CODEVISIONAVR__)\r
+  #asm("cli");\r
+#else\r
   cli();\r
+#endif\r
 #endif\r
 \r
   // increment tail position\r
@@ -445,7 +579,11 @@ static unsigned char WaitRxChar (void) {
 \r
 #if USE_CTS\r
   CTS_PORT |= (1<<CTS_PIN); // Ensure CTS is active since just removed a byte\r
+#if defined(__CODEVISIONAVR__)\r
+  #asm("sei");\r
+#else\r
   sei();   // Allow UART ISR to read character and change potentially change CTS\r
+#endif\r
 #endif\r
 \r
   return sUartRxBuf[sUartRxTail];\r
@@ -454,11 +592,17 @@ static unsigned char WaitRxChar (void) {
 #if defined(__IMAGECRAFT__)\r
 #pragma interrupt_handler timer0_compa_handler:iv_TIMER0_COMPA\r
 void timer0_compa_handler(void)\r
+#elif defined(__CODEVISIONAVR__)\r
+interrupt [TIM0_COMPA] void timer0_compa_handler(void)\r
 #else\r
   ISR(TIMER0_COMPA_vect)\r
 #endif\r
 {\r
+#if defined(__CODEVISIONAVR__)\r
+  #asm("sei");\r
+#else\r
   sei(); // Okay to allow USART interrupts while controlling LED PWM\r
+#endif\r
 \r
   // Set current LED state based on cycling variable\r
   if (ledPwmCycling & 0x01) {\r