spi_7seg.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2008-2009 by egnite GmbH
00003  * Copyright (C) 2006 by egnite Software GmbH
00004  *
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions
00009  * are met:
00010  *
00011  * 1. Redistributions of source code must retain the above copyright
00012  *    notice, this list of conditions and the following disclaimer.
00013  * 2. Redistributions in binary form must reproduce the above copyright
00014  *    notice, this list of conditions and the following disclaimer in the
00015  *    documentation and/or other materials provided with the distribution.
00016  * 3. Neither the name of the copyright holders nor the names of
00017  *    contributors may be used to endorse or promote products derived
00018  *    from this software without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00027  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00028  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00029  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00030  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00031  * SUCH DAMAGE.
00032  *
00033  * For additional information see http://www.ethernut.de/
00034  */
00035 
00045 #include <cfg/os.h>
00046 
00047 #include <sys/nutdebug.h>
00048 #include <sys/timer.h>
00049 
00050 #include <string.h>
00051 #include <stdio.h>
00052 
00053 
00054 
00055 #define SEG_NOOP 0x00
00056 #define SEG_DIG0 0x01
00057 #define SEG_DIG1 0x02
00058 #define SEG_DIG2 0x03
00059 #define SEG_DIG3 0x04
00060 #define SEG_DIG4 0x05
00061 #define SEG_DIG5 0x06
00062 #define SEG_DIG6 0x07
00063 #define SEG_DIG7 0x08
00064 #define SEG_DEC_MODE    0x09
00065 #define SEG_INTENSITY   0x0a
00066 #define SEG_SCAN_LIM    0x0b
00067 #define SEG_SHUTDOWN    0x0c
00068 #define SEG_FEATURE     0x0e
00069 #define SEG_DSP_TEST    0x0f
00070 
00071 /* shutdown register (0x0c) */
00072 #define SHUTDOWN_RESET  0x00
00073 #define SHUTDOWN_SOFT   0x80
00074 #define NORM_OP_RESET   0x01
00075 #define NORM_OP_SOFT    0x81
00076 
00077 /* decode en register (0x09) */
00078 #define NO_DIG_DECODE   0x00
00079 #define DIG_0_DECODE    0x01
00080 #define DIG_0_3_DECODE  0x0f
00081 #define DIG_0_7_DECODE  0xff
00082 
00083 #define TEST_MODE_OFF   0x00
00084 #define TEST_MODE_ON    0x01
00085 
00086 /* scan limit register (0x0b) */
00087 #define DISPLAY_LIMIT   2
00088 
00089 #define MAX_7SEG_DIGITS 3
00090 
00091 
00092 #ifndef DISP_7SEG_WRITE_POLLS
00093 #define DISP_7SEG_WRITE_POLLS        1000
00094 #endif
00095 
00096 
00097 
00098 #include <cfg/memory.h>
00099 
00100 #include <dev/blockdev.h>
00101 #include <dev/spi_7seg.h>
00102 
00103 #ifndef SPI_RATE_DISP_7SEG
00104 #define SPI_RATE_DISP_7SEG  1000000
00105 //#define SPI_RATE_DISP_7SEG  2000000
00106 // #define SPI_RATE_DISP_7SEG  4000000
00107 // #define SPI_RATE_DISP_7SEG  8000000
00108 //#define SPI_RATE_DISP_7SEG  16000000
00109 #endif
00110 
00111 #ifndef SPI_MODE_DISP_7SEG
00112 #ifdef SPI_CSHIGH_DISP_7SEG
00113 #define SPI_MODE_DISP_7SEG (SPI_MODE_3 | SPI_MODE_CSHIGH)
00114 #else
00115 #define SPI_MODE_DISP_7SEG SPI_MODE_3
00116 #endif
00117 #endif
00118 
00119 #include <cfg/arch/gpio.h>
00120 #include <dev/spibus_at91.h>
00121 
00125 NUTSPINODE nodeSpi7SEG = {
00126     &NUT_CONFIG_7SEG_SPIBUS,      
00127     NULL,                       
00128     SPI_RATE_DISP_7SEG,            
00129     SPI_MODE_DISP_7SEG,            
00130     8,                          
00131     NUT_CONFIG_7SEG_CS                           
00132 };
00133 
00137 NUTDEVICE devSpi7SEG = {
00138     NULL,                               
00139     {'7', 'S', 'E', 'G', 0, 0, 0},      
00140     IFTYP_BLKIO,                        
00141     0,                                  
00142     0,                                  
00143     &nodeSpi7SEG,                       
00144     0,                                  
00145     Spi7segInit,                        
00146     0,                                  
00147     0,                                  
00148     0,                                  
00149 #ifdef __HARVARD_ARCH__
00150     0,                                  
00151 #endif
00152     0,                                  
00153     0,                                  
00154     0                                   
00155 };
00156 
00166 static int disp7segCommand(NUTSPINODE * node, uint8_t addr, CONST void *txbuf, void *rxbuf, int xlen)
00167 {
00168     int rc = -1;
00169     NUTSPIBUS *bus;
00170     uint8_t *tmp;
00171     uint8_t cmd[2];
00172 
00173     NUTASSERT(node != NULL);
00174     bus = (NUTSPIBUS *) node->node_bus;
00175     NUTASSERT(bus != NULL);
00176     NUTASSERT(bus->bus_alloc != NULL);
00177     NUTASSERT(bus->bus_transfer != NULL);
00178     NUTASSERT(bus->bus_release != NULL);
00179 
00180     /* write address */
00181      cmd[0] = addr;
00182     
00183     tmp = (uint8_t *)txbuf;
00184     /* write data */
00185      cmd[1] = tmp[0];
00186     //cmd[1] = (uint8_t )txbuf[0];
00187     /* write data */
00188     rc = (*bus->bus_alloc) (node, 1000);
00189     if (rc == 0) {
00190         rc = (*bus->bus_transfer) (node, cmd, NULL, 2);
00191 
00192         (*bus->bus_release) (node);
00193     }
00194     return rc;
00195 }
00196 
00197 
00210 int Spi7segInit(NUTDEVICE * dev)
00211 {
00212     uint8_t data;
00213 //  uint8_t cmd;
00214 //  int rc;
00215  //   NUTBLOCKIO *blkio;
00216     NUTSPINODE *node;
00217    // uint8_t sr;
00218     //int_fast8_t i;
00219 
00220     NUTASSERT(dev != NULL);
00221     NUTASSERT(dev->dev_dcb != NULL);
00222     NUTASSERT(dev->dev_icb != NULL);
00223     //blkio = dev->dev_dcb;
00224    node = dev->dev_icb;
00225     data = TEST_MODE_OFF;
00226     disp7segCommand(node, SEG_DSP_TEST, &data, NULL, 1);
00227     
00228     disp7segCommand(node, SEG_DSP_TEST, &data, NULL, 1);
00229     
00230     disp7segCommand(node, SEG_DSP_TEST, &data, NULL, 1);
00231     
00232     data = NORM_OP_RESET;
00233     disp7segCommand(node, SEG_SHUTDOWN, &data, NULL, 1);
00234     
00235     data = 2;
00236     disp7segCommand(node, SEG_SCAN_LIM, &data, NULL, 1);
00237     
00238     data = NO_DIG_DECODE;
00239     disp7segCommand(node, SEG_DEC_MODE, &data, NULL, 1);
00240     
00241     data = 0x0F;
00242     disp7segCommand(node, SEG_INTENSITY, &data, NULL, 1);
00243     
00244     data = 0;
00245     disp7segCommand(node, SEG_DIG0, &data, NULL, 1);
00246     
00247     disp7segCommand(node, SEG_DIG1, &data, NULL, 1);
00248     
00249     disp7segCommand(node, SEG_DIG2, &data, NULL, 1);
00250     
00251     return 0;
00252 
00253 }
00254 
00255 
00256 
00257 static const unsigned char CharLookup[] = {
00258     /* '0' */(0x7E),
00259     /* '1' */(0x30),
00260     /* '2' */(0x6D),
00261     /* '3' */(0x79),
00262     /* '4' */(0x33),
00263     /* '5' */(0x5B),
00264     /* '6' */(0x5F),
00265     /* '7' */(0x70),
00266     /* '8' */(0x7F),
00267     /* '9' */(0x7B),
00268     /* 'A' */(0x77),
00269     /* 'b' */(0x1F),
00270     /* 'c' */(0x0D),
00271     /* 'd' */(0x3D),
00272     /* 'E' */(0x4F),
00273     /* 'F' */(0x47),
00274     /* 'G' */(0x5F),
00275     /* 'H' */(0x37),
00276     /* 'i' */(0x10),
00277     /* 'J' */(0x3C),
00278     /* 'K' */(0x0F),
00279     /* 'L' */(0x0E),
00280     /* 'M' */(0x76),
00281     /* 'N' */(0x15),
00282     /* 'O' */(0x1D),
00283     /* 'P' */(0x67),
00284     /* 'Q' */(0x73),
00285     /* 'R' */(0x05),
00286     /* 'S' */(0x5B),
00287     /* 'T' */(0x0F),
00288     /* 'U' */(0x3E),
00289     /* 'V' */(0x1C),
00290     /* 'W' */(0x3F),
00291     /* 'X' */(0x37),
00292     /* 'Y' */(0x3B),
00293     /* 'Z' */(0x6D),
00294     /* '-' */(0x01),
00295     /*set point on lower right side*/
00296 //  {'.', (unsigned char)DISPL_DP},
00297     /*unset point on lower right side*/
00298 //  {'^', (unsigned char)~(DISPL_DP)},
00299     /*
00300     switch all segments off
00301     NOTE do not remove the line below!
00302     */
00303 //  {' ', (unsigned char)DISPL_OFF},
00304 };
00305 #define HUNDRED 2
00306 #define TENNER 1
00307 #define ANY 0
00308 void display_7seg(NUTDEVICE * dev, uint16_t number)
00309 {
00310     uint8_t display[3], next=0;
00311     NUTSPINODE *node;
00312     NUTASSERT(dev->dev_icb != NULL);
00313     node = dev->dev_icb;
00314     
00315         if (number< 1000) 
00316         {/*distance between 0 and 99,9 meters*/
00317            display[HUNDRED]        = number / 100;
00318            display[TENNER]              = (number % 100) / 10;
00319            display[ANY]     = (number % 100) % 10;
00320         }
00321     else 
00322         {
00323          /*TODO FEHLER anzeigen */
00324         }
00325        
00326 
00327     for (next=0;next < 3;next++)
00328     {
00329         disp7segCommand(node,  2-next+1, &CharLookup[display[next]], NULL, 1);
00330         // printf("addr: %d data:0x%2X\n",2-next+1,CharLookup[display[next]] );
00331     }
00332 }
00333 
00334 uint8_t display_buffer[MAX_7SEG_DIGITS] = { 0, 0, 0 };
00335 
00336 void print_7seg(NUTDEVICE *dev, char* chars)
00337 {
00338     uint8_t count=0;
00339     NUTSPINODE *node;
00340     NUTASSERT(dev->dev_icb != NULL);
00341     node = dev->dev_icb;
00342     for(count=0; count<MAX_7SEG_DIGITS; count++)
00343     {
00344         uint8_t display = 0;
00345         if(chars[count] == 0)
00346         {
00347             break;
00348         }
00349         else if(chars[count] >= '0' && chars[count] <= '9')
00350         {
00351             display = CharLookup[chars[count] - '0'];
00352         }
00353         else if(chars[count] >= 'A' && chars[count] <= 'Z')
00354         {
00355             display = CharLookup[chars[count] - 'A' + 10];
00356         }
00357         else if(chars[count] >= 'a' && chars[count] <= 'z')
00358         {
00359             display = CharLookup[chars[count] - 'a' + 10];
00360         }
00361         else if(chars[count] == '-')
00362         {
00363             display = CharLookup[36];
00364         }
00365         //save char independent of decimal point
00366         display_buffer[count] &= 0x80;
00367         display_buffer[count] |= (display & 0x7F);
00368         disp7segCommand(node, MAX_7SEG_DIGITS-count, &(display_buffer[count]), NULL, 1);
00369     }
00370 }
00371 
00372 void dot_7seg(NUTDEVICE *dev, uint8_t dotNumber, uint8_t dotCommand)
00373 {
00374     uint8_t count=0;
00375     NUTSPINODE *node;
00376     NUTASSERT(dev->dev_icb != NULL);
00377     node = dev->dev_icb;
00378     if(dotNumber<MAX_7SEG_DIGITS)
00379     {
00380         switch(dotCommand)
00381         {
00382             case DOT_7SEG_SET:
00383                 display_buffer[MAX_7SEG_DIGITS-dotNumber-1] |= 0x80;
00384                 break;
00385             case DOT_7SEG_CLEAR:
00386                 display_buffer[MAX_7SEG_DIGITS-dotNumber-1] &= 0x7F;
00387                 break;
00388             case DOT_7SEG_FLIP:
00389                 display_buffer[MAX_7SEG_DIGITS-dotNumber-1] ^= 0x80;
00390                 break;
00391             default:
00392                 break;
00393         }
00394     }
00395     for(count=0; count<MAX_7SEG_DIGITS; count++)
00396     {
00397         disp7segCommand(node, MAX_7SEG_DIGITS-count, &(display_buffer[count]), NULL, 1);
00398     }
00399 }

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/