iforce2d Chris / Mbed 2 deprecated ubxDistanceMeter

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers u8g_com_arduino_hw_spi.c Source File

u8g_com_arduino_hw_spi.c

00001 /*
00002   
00003   u8g_com_arduino_hw_spi.c
00004 
00005   Universal 8bit Graphics Library
00006   
00007   Copyright (c) 2011, olikraus@gmail.com
00008   All rights reserved.
00009 
00010   Redistribution and use in source and binary forms, with or without modification, 
00011   are permitted provided that the following conditions are met:
00012 
00013   * Redistributions of source code must retain the above copyright notice, this list 
00014     of conditions and the following disclaimer.
00015     
00016   * Redistributions in binary form must reproduce the above copyright notice, this 
00017     list of conditions and the following disclaimer in the documentation and/or other 
00018     materials provided with the distribution.
00019 
00020   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 
00021   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
00022   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
00023   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00024   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 
00025   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
00026   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
00027   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
00028   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
00029   CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
00030   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
00031   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
00032   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  
00033 
00034   SPI Clock Cycle Type
00035   
00036   SSD1351     50ns      20 MHz
00037   SSD1322   300ns         3.3 MHz
00038   SSD1327   300ns
00039   SSD1306   300ns
00040   ST7565        400ns         2.5 MHz
00041   ST7920        400ns
00042 
00043   Arduino DUE
00044   
00045   PA25  MISO
00046   PA26  MOSI    75
00047   PA27  SCLK    76
00048   
00049   
00050 typedef struct {
00051   WoReg SPI_CR;        (Spi Offset: 0x00) Control Register 
00052   RwReg SPI_MR;        (Spi Offset: 0x04) Mode Register 
00053   RoReg SPI_RDR;       (Spi Offset: 0x08) Receive Data Register 
00054   WoReg SPI_TDR;       (Spi Offset: 0x0C) Transmit Data Register 
00055   RoReg SPI_SR;        (Spi Offset: 0x10) Status Register 
00056   WoReg SPI_IER;       (Spi Offset: 0x14) Interrupt Enable Register 
00057   WoReg SPI_IDR;       (Spi Offset: 0x18) Interrupt Disable Register 
00058   RoReg SPI_IMR;       (Spi Offset: 0x1C) Interrupt Mask Register 
00059   RoReg Reserved1[4];
00060   RwReg SPI_CSR[4];    (Spi Offset: 0x30) Chip Select Register 
00061   RoReg Reserved2[41];
00062   RwReg SPI_WPMR;      (Spi Offset: 0xE4) Write Protection Control Register 
00063   RoReg SPI_WPSR;      (Spi Offset: 0xE8) Write Protection Status Register 
00064 } Spi;
00065   
00066   Power Management Controller (PMC)
00067   arduino-1.5.2/hardware/arduino/sam/system/CMSIS/Device/ATMEL/sam3xa/include/instance/instance_pmc.h
00068     - enable PIO
00069       
00070       REG_PMC_PCER0 = 1UL << ID_PIOA
00071     - enable SPI
00072       REG_PMC_PCER0 = 1UL << ID_SPI0
00073 
00074 
00075     - enable PIOA and SPI0
00076       REG_PMC_PCER0 = (1UL << ID_PIOA) | (1UL << ID_SPI0);
00077 
00078   Parallel Input/Output Controller (PIO)
00079   arduino-1.5.2/hardware/arduino/sam/system/CMSIS/Device/ATMEL/sam3xa/include/instance/instance_pioa.h
00080     - enable special function of the pin: disable PIO on A26 and A27:
00081     REG_PIOA_PDR = 0x0c000000
00082     PIOA->PIO_PDR = 0x0c000000
00083 
00084   SPI
00085     SPI0->SPI_CR = SPI_CR_SPIDIS
00086     SPI0->SPI_CR = SPI_CR_SWRST ;
00087     SPI0->SPI_CR = SPI_CR_SWRST ;
00088     SPI0->SPI_CR = SPI_CR_SPIEN
00089   
00090     Bit 0: Master Mode = 1 (active)
00091     Bit 1: Peripheral Select = 0 (fixed)
00092     Bit 2: Chip Select Decode Mode = 1 (4 to 16)
00093     Bit 4: Mode Fault Detection = 1 (disabled)
00094     Bit 5: Wait Data Read = 0 (disabled) 
00095     Bit 7: Loop Back Mode = 0 (disabled)
00096     Bit 16-19: Peripheral Chip Select = 0 (chip select 0)    
00097     SPI0->SPI_MR = SPI_MR_MSTR | SPI_MR_PCSDEC | SPI_MR_MODFDIS
00098     
00099     Bit 0: Clock Polarity = 0
00100     Bit 1: Clock Phase = 0
00101     Bit 4-7: Bits = 0 (8 Bit)
00102     Bit 8-15: SCBR = 1
00103     SPI0->SPI_CSR[0] = SPI_CSR_SCBR(x)  Serial Baud Rate
00104     SCBR / 84000000 > 50 / 1000000000 
00105     SCBR / 84 > 5 / 100 
00106     SCBR  > 50 *84 / 1000 --> SCBR=5
00107     SCBR  > 300*84 / 1000 --> SCBR=26
00108     SCBR  > 400*84 / 1000 --> SCBR=34
00109 
00110   Arduino Due test code:
00111     REG_PMC_PCER0 = (1UL << ID_PIOA) | (1UL << ID_SPI0);
00112     REG_PIOA_PDR = 0x0c000000;
00113     SPI0->SPI_CR = SPI_CR_SPIDIS;
00114     SPI0->SPI_CR = SPI_CR_SWRST;
00115     SPI0->SPI_CR = SPI_CR_SWRST;
00116     SPI0->SPI_CR = SPI_CR_SPIEN;
00117     SPI0->SPI_MR = SPI_MR_MSTR | SPI_MR_PCSDEC | SPI_MR_MODFDIS;
00118     SPI0->SPI_CSR[0] = SPI_CSR_SCBR(30);
00119 
00120     for(;;)
00121     {
00122       while( (SPI0->SPI_SR & SPI_SR_TDRE) == 0 )
00123     ;
00124       SPI0->SPI_TDR = 0x050;
00125     }
00126 
00127 */
00128 
00129 #include "u8g.h"
00130 
00131 #if defined(ARDUINO)
00132 
00133 #if defined(__AVR__)
00134 #define U8G_ARDUINO_ATMEGA_HW_SPI
00135 /* remove the definition for attiny */
00136 #if __AVR_ARCH__ == 2
00137 #undef U8G_ARDUINO_ATMEGA_HW_SPI
00138 #endif
00139 #if __AVR_ARCH__ == 25
00140 #undef U8G_ARDUINO_ATMEGA_HW_SPI
00141 #endif
00142 #endif
00143 
00144 #if defined(U8G_ARDUINO_ATMEGA_HW_SPI)
00145 
00146 #include <avr/interrupt.h>
00147 #include <avr/io.h>
00148 
00149 #if ARDUINO < 100 
00150 #include <WProgram.h> 
00151 
00152 /* fixed pins */
00153 #if defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__) // Sanguino.cc board
00154 #define PIN_SCK         7
00155 #define PIN_MISO        6
00156 #define PIN_MOSI        5
00157 #define PIN_CS          4
00158 #else                                   // Arduino Board
00159 #define PIN_SCK 13
00160 #define PIN_MISO  12
00161 #define PIN_MOSI 11
00162 #define PIN_CS 10
00163 #endif // (__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__)
00164 
00165 #else 
00166 
00167 #include <Arduino.h> 
00168 
00169 /* use Arduino pin definitions */
00170 #define PIN_SCK SCK
00171 #define PIN_MISO  MISO
00172 #define PIN_MOSI MOSI
00173 #define PIN_CS SS
00174 
00175 #endif
00176 
00177 
00178 
00179 //static uint8_t u8g_spi_out(uint8_t data) U8G_NOINLINE;
00180 static uint8_t u8g_spi_out(uint8_t data)
00181 {
00182   /* unsigned char x = 100; */
00183   /* send data */
00184   SPDR = data;
00185   /* wait for transmission */
00186   while (!(SPSR & (1<<SPIF))) 
00187     ;
00188   /* clear the SPIF flag by reading SPDR */
00189   return  SPDR;
00190 }
00191 
00192 
00193 uint8_t u8g_com_arduino_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr)
00194 {
00195   switch(msg)
00196   {
00197     case U8G_COM_MSG_STOP:
00198       break;
00199     
00200     case U8G_COM_MSG_INIT:
00201       u8g_com_arduino_assign_pin_output_high(u8g);
00202       pinMode(PIN_SCK, OUTPUT);
00203       digitalWrite(PIN_SCK, LOW);
00204       pinMode(PIN_MOSI, OUTPUT);
00205       digitalWrite(PIN_MOSI, LOW);
00206       /* pinMode(PIN_MISO, INPUT); */
00207 
00208       pinMode(PIN_CS, OUTPUT);          /* system chip select for the atmega board */
00209       digitalWrite(PIN_CS, HIGH);
00210     
00211 
00212 
00213       /*
00214         SPR1 SPR0
00215             0   0       fclk/4
00216             0   1       fclk/16
00217             1   0       fclk/64
00218             1   1       fclk/128
00219       */
00220       SPCR = 0;
00221       SPCR =  (1<<SPE) | (1<<MSTR)|(0<<SPR1)|(0<<SPR0)|(0<<CPOL)|(0<<CPHA);
00222 #ifdef U8G_HW_SPI_2X
00223       SPSR = (1 << SPI2X);  /* double speed, issue 89 */
00224 #else
00225       if ( arg_val  <= U8G_SPI_CLK_CYCLE_50NS )
00226       {
00227     SPSR = (1 << SPI2X);  /* double speed, issue 89 */
00228       }
00229 #endif
00230       
00231       
00232       break;
00233     
00234     case U8G_COM_MSG_ADDRESS:                     /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
00235       u8g_com_arduino_digital_write(u8g, U8G_PI_A0, arg_val);
00236       break;
00237 
00238     case U8G_COM_MSG_CHIP_SELECT:
00239       if ( arg_val == 0 )
00240       {
00241         /* disable */
00242         u8g_com_arduino_digital_write(u8g, U8G_PI_CS, HIGH);
00243       }
00244       else
00245       {
00246         /* enable */
00247         u8g_com_arduino_digital_write(u8g, U8G_PI_SCK, LOW);
00248         u8g_com_arduino_digital_write(u8g, U8G_PI_CS, LOW);
00249       }
00250       break;
00251       
00252     case U8G_COM_MSG_RESET:
00253       if ( u8g->pin_list[U8G_PI_RESET] != U8G_PIN_NONE )
00254         u8g_com_arduino_digital_write(u8g, U8G_PI_RESET, arg_val);
00255       break;
00256     
00257     case U8G_COM_MSG_WRITE_BYTE:
00258       u8g_spi_out(arg_val);
00259       break;
00260     
00261     case U8G_COM_MSG_WRITE_SEQ:
00262       {
00263         register uint8_t *ptr = arg_ptr;
00264         while( arg_val > 0 )
00265         {
00266           u8g_spi_out(*ptr++);
00267           arg_val--;
00268         }
00269       }
00270       break;
00271     case U8G_COM_MSG_WRITE_SEQ_P:
00272       {
00273         register uint8_t *ptr = arg_ptr;
00274         while( arg_val > 0 )
00275         {
00276           u8g_spi_out(u8g_pgm_read(ptr));
00277           ptr++;
00278           arg_val--;
00279         }
00280       }
00281       break;
00282   }
00283   return 1;
00284 }
00285 
00286 /* #elif defined(__18CXX) || defined(__PIC32MX) */
00287 
00288 #elif defined(__arm__)      // Arduino Due, maybe we should better check for __SAM3X8E__
00289 
00290 #include <Arduino.h> 
00291 
00292 /* use Arduino pin definitions */
00293 #define PIN_SCK SCK
00294 #define PIN_MISO  MISO
00295 #define PIN_MOSI MOSI
00296 #define PIN_CS SS
00297 
00298 
00299 static uint8_t u8g_spi_out(uint8_t data)
00300 {
00301   /* wait until tx register is empty */
00302   while( (SPI0->SPI_SR & SPI_SR_TDRE) == 0 )
00303     ;
00304   /* send data */
00305   SPI0->SPI_TDR = (uint32_t)data;
00306   return  data;
00307 }
00308 
00309 
00310 uint8_t u8g_com_arduino_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr)
00311 {
00312   switch(msg)
00313   {
00314     case U8G_COM_MSG_STOP:
00315       break;
00316     
00317     case U8G_COM_MSG_INIT:
00318       u8g_com_arduino_assign_pin_output_high(u8g);
00319       u8g_com_arduino_digital_write(u8g, U8G_PI_CS, HIGH);
00320     
00321       /* Arduino Due specific code */
00322       
00323       /* enable PIOA and SPI0 */
00324       REG_PMC_PCER0 = (1UL << ID_PIOA) | (1UL << ID_SPI0);
00325 
00326       /* disable PIO on A26 and A27 */
00327       REG_PIOA_PDR = 0x0c000000;
00328 
00329       /* reset SPI0 (from sam lib) */
00330       SPI0->SPI_CR = SPI_CR_SPIDIS;
00331       SPI0->SPI_CR = SPI_CR_SWRST;
00332       SPI0->SPI_CR = SPI_CR_SWRST;
00333       SPI0->SPI_CR = SPI_CR_SPIEN;
00334       u8g_MicroDelay();
00335       
00336       /* master mode, no fault detection, chip select 0 */
00337       SPI0->SPI_MR = SPI_MR_MSTR | SPI_MR_PCSDEC | SPI_MR_MODFDIS;
00338       
00339       /* Polarity, Phase, 8 Bit data transfer, baud rate */
00340       /* x * 1000 / 84 --> clock cycle in ns 
00341         5 * 1000 / 84 = 58 ns       
00342     SCBR  > 50 *84 / 1000 --> SCBR=5
00343     SCBR  > 300*84 / 1000 --> SCBR=26
00344     SCBR  > 400*84 / 1000 --> SCBR=34
00345       */
00346       
00347       if ( arg_val <= U8G_SPI_CLK_CYCLE_50NS )
00348       {
00349     SPI0->SPI_CSR[0] = SPI_CSR_SCBR(5) | 1;
00350       }
00351       else if ( arg_val <= U8G_SPI_CLK_CYCLE_300NS )
00352       {
00353     SPI0->SPI_CSR[0] = SPI_CSR_SCBR(26) | 1;
00354       }
00355       else if ( arg_val <= U8G_SPI_CLK_CYCLE_400NS )
00356       {
00357     SPI0->SPI_CSR[0] = SPI_CSR_SCBR(34) | 1;
00358       }
00359       else
00360       {
00361     SPI0->SPI_CSR[0] = SPI_CSR_SCBR(84) | 1;
00362       }
00363       
00364       u8g_MicroDelay();      
00365       break;
00366     
00367     case U8G_COM_MSG_ADDRESS:                     /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
00368       u8g_com_arduino_digital_write(u8g, U8G_PI_A0, arg_val);
00369       u8g_MicroDelay();
00370       break;
00371 
00372     case U8G_COM_MSG_CHIP_SELECT:
00373       if ( arg_val == 0 )
00374       {
00375         /* disable */
00376     u8g_MicroDelay();       /* this delay is required to avoid that the display is switched off too early --> DOGS102 with DUE */
00377         u8g_com_arduino_digital_write(u8g, U8G_PI_CS, HIGH);
00378     u8g_MicroDelay();
00379       }
00380       else
00381       {
00382         /* enable */
00383         //u8g_com_arduino_digital_write(u8g, U8G_PI_SCK, LOW);
00384         u8g_com_arduino_digital_write(u8g, U8G_PI_CS, LOW);
00385     u8g_MicroDelay();
00386       }
00387       break;
00388       
00389     case U8G_COM_MSG_RESET:
00390       if ( u8g->pin_list[U8G_PI_RESET] != U8G_PIN_NONE )
00391         u8g_com_arduino_digital_write(u8g, U8G_PI_RESET, arg_val);
00392       break;
00393     
00394     case U8G_COM_MSG_WRITE_BYTE:
00395       u8g_spi_out(arg_val);
00396       u8g_MicroDelay();
00397       break;
00398     
00399     case U8G_COM_MSG_WRITE_SEQ:
00400       {
00401         register uint8_t *ptr = arg_ptr;
00402         while( arg_val > 0 )
00403         {
00404           u8g_spi_out(*ptr++);
00405           arg_val--;
00406         }
00407       }
00408       break;
00409     case U8G_COM_MSG_WRITE_SEQ_P:
00410       {
00411         register uint8_t *ptr = arg_ptr;
00412         while( arg_val > 0 )
00413         {
00414           u8g_spi_out(u8g_pgm_read(ptr));
00415           ptr++;
00416           arg_val--;
00417         }
00418       }
00419       break;
00420   }
00421   return 1;
00422 }
00423 
00424 
00425 
00426 #else /* U8G_ARDUINO_ATMEGA_HW_SPI */
00427 
00428 #endif /* U8G_ARDUINO_ATMEGA_HW_SPI */
00429 
00430 #else /* ARDUINO */
00431 
00432 uint8_t u8g_com_arduino_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr)
00433 {
00434   return 1;
00435 }
00436 
00437 #endif /* ARDUINO */
00438 
00439