Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
Generated on Tue Jul 12 2022 17:30:57 by
1.7.2