Carmel (MAXREFDES18#) Code Documentation  V01.00
High Accuracy Analog Current/Voltage Output
 All Data Structures Files Functions Variables Macros Pages
utilities.c
Go to the documentation of this file.
1 
29 /*
30  * Copyright (C) 2012 Maxim Integrated Products, Inc., All Rights Reserved.
31  *
32  * Permission is hereby granted, free of charge, to any person obtaining a
33  * copy of this software and associated documentation files (the "Software"),
34  * to deal in the Software without restriction, including without limitation
35  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
36  * and/or sell copies of the Software, and to permit persons to whom the
37  * Software is furnished to do so, subject to the following conditions:
38  *
39  * The above copyright notice and this permission notice shall be included
40  * in all copies or substantial portions of the Software.
41  *
42  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
43  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
44  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
45  * IN NO EVENT SHALL MAXIM INTEGRATED PRODUCTS BE LIABLE FOR ANY CLAIM, DAMAGES
46  * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
47  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
48  * OTHER DEALINGS IN THE SOFTWARE.
49  *
50  * Except as contained in this notice, the name of Maxim Integrated Products
51  * shall not be used except as stated in the Maxim Integrated Products
52  * Branding Policy.
53  *
54  * The mere transfer of this software does not imply any licenses
55  * of trade secrets, proprietary technology, copyrights, patents,
56  * trademarks, maskwork rights, or any other form of intellectual
57  * property whatsoever. Maxim Integrated Products retains all ownership rights.
58  *
59  ***************************************************************************/
60 
61 #include "utilities.h"
62 
63 #define OLED_VBAT 0x20
64 #define OLED_VDD 0x10;
65 #define OLED_RESET_B 0x08
66 #define OLED_DATA_COMMAND_B 0x04
67 #define OLED_SDIN 0x02
68 #define OLED_SCLK 0x01
69 
70 void sendUartByte(u32 unUartAddress, u8 uchByte)
79 {
80  if(unUartAddress==DEFAULT_HYPERTERMINAL_UART_ADDRESS)
81  {
82  printf("%c",uchByte);
83  fflush(stdout);
84  }
85  else
86  XUartLite_SendByte(unUartAddress, uchByte);
87 }
88 
89 u8 checkUartEmpty(u32 unUartAddress)
97 {
98  u8 uchReturnVal=TRUE;
99  u32 unUartStatusRegisterAddress;
100  u32 unStatusRegisterValue;
101  if(unUartAddress==XPAR_PS7_UART_1_BASEADDR)
102  {
103  unUartStatusRegisterAddress = unUartAddress + 0x0000002C;
104  unStatusRegisterValue = Xil_In32(unUartStatusRegisterAddress);
105 
106  // Register UART BASE ADDR + 0x2C. Bit 1 is a (1) when Rx FIFO is empty
107  if((unStatusRegisterValue & 0x00000002)==0x00000002)
108  uchReturnVal=TRUE;
109  else
110  uchReturnVal=FALSE;
111  }
112  else
113  {
114  if(XUartLite_IsReceiveEmpty(unUartAddress)==TRUE)
115  uchReturnVal=TRUE;
116  else
117  uchReturnVal=FALSE;
118  }
119  return(uchReturnVal);
120 }
121 
122 
123 u8 getUartByte(u32 nUartAddress)
131 {
132  u8 uchInput;
133 
134  // Check if the UART base address is the full UART located within the Zynq chip,
135  // if not, assume it is an HDL instantiated AXI-UartLite
136  if(nUartAddress==XPAR_PS7_UART_1_BASEADDR)
137  read(1, (char*)&uchInput, 1); // Get a byte from stdin
138  else
139  uchInput = XUartLite_RecvByte(nUartAddress);
140  return(uchInput);
141 }
142 
143 void print_asterisks(int nQuantity)
151 {
152  int i=0;
153  for(i=0;i<nQuantity;i++)
154  printf("*");
155 }
156 
157 int SpiRW( u32 unPeripheralAddressSPI, unsigned int unCPHA, unsigned int unCPOL,
158  u8* auchWriteBuf, u8* auchReadBuf, int unNumBytes, u8 uchCsActiveHigh, u32 unSpiSS)
181 {
182  int i;
183  unsigned int unControlData = 0x00000186;
184 
185  //If CPHA or CPOL = 1, we need to set the corresponding bits in the control register
186  unControlData = unControlData | (unCPHA << 4);
187  unControlData = unControlData | (unCPOL << 3);
188 
189  //Write config data to SPICR. We need the inhibit bit=1.
190  XSpi_WriteReg(unPeripheralAddressSPI, 0x60, unControlData);
191 
192  //Deassert CS to 1 to ensure SPI slave is inactive
193  if( uchCsActiveHigh )
194  XSpi_WriteReg(unPeripheralAddressSPI, 0x70, unSpiSS == 0x1? 0xFFFFFFFE : 0xFFFFFFD);
195  else
196  XSpi_WriteReg(unPeripheralAddressSPI, 0x70, 0xFFFFFFFF);
197 
198  for( i = 0; i < unNumBytes; i++)
199  {
200  if( auchWriteBuf != 0 )
201  {
202  //Write data to SPIDTR. This is the data that will be transferred to the SPI slave.
203  XSpi_WriteReg(unPeripheralAddressSPI, 0x68, auchWriteBuf[ i ]);
204  //Debug//printf( "Write %02x; ", auchWriteBuf[i]);
205  }
206  else
207  {
208  //Write data to SPIDTR. This is the data that will be transferred to the SPI slave.
209  XSpi_WriteReg(unPeripheralAddressSPI, 0x68, 0x00);
210  }
211 
212  //Write config data to SPICR. We need the inhibit bit=1.
213  XSpi_WriteReg(unPeripheralAddressSPI, 0x60, unControlData);
214 
215  //Assert CS for our PMOD part
216  if( uchCsActiveHigh )
217  XSpi_WriteReg(unPeripheralAddressSPI, 0x70, 0xFFFFFFFF);
218  else
219  XSpi_WriteReg(unPeripheralAddressSPI, 0x70, unSpiSS == 0x1? 0xFFFFFFFE : 0xFFFFFFFD);
220 
221  //Un-inhibit our SPI master to transfer the data
222  XSpi_WriteReg(unPeripheralAddressSPI, 0x60, unControlData & 0xFFFFFEFF);
223 
224  //Wait for transaction to complete. Check to see if Tx_Empty flag is set before proceeding.
225  while( !(XSpi_ReadReg( unPeripheralAddressSPI, 0x64 ) & 0x00000004) )
226  ;
227 
228  //Inhibit SPI master to prevent further action
229  XSpi_WriteReg(unPeripheralAddressSPI, 0x60, unControlData);
230 
231  //Read received data
232  if( (auchReadBuf != 0) )
233  {
234  auchReadBuf[ i ] = XSpi_ReadReg(unPeripheralAddressSPI, 0x6C);
235  //Debug//printf( "Read %02x\r\n", auchReadBuf[i]);
236  }
237  }
238  if( uchCsActiveHigh )
239  XSpi_WriteReg(unPeripheralAddressSPI, 0x70, unSpiSS == 0x1? 0xFFFFFFFE : 0xFFFFFFFD);
240  else
241  XSpi_WriteReg(unPeripheralAddressSPI, 0x70, 0xFFFFFFFF);
242  return 0;
243 }
244 
245 void delay(int nStopValue)
256 {
257  int i=0;
258  int a=0;
259 
260  for(i=0;i<nStopValue;i++)
261  {
262  a=i;
263  }
264 }
265 
266 void led_knight_rider(XGpio *pLED_GPIO, int nNumberOfTimes)
277 {
278  int i=0;
279  int j=0;
280  u8 uchLedStatus=0;
281 
282  // Blink the LEDs back and forth nNumberOfTimes
283  for(i=0;i<nNumberOfTimes;i++)
284  {
285  for(j=0;j<8;j++) // Scroll the LEDs up
286  {
287  uchLedStatus = 1 << j;
288  XGpio_DiscreteWrite(pLED_GPIO, 1, uchLedStatus);
289  delay(ABOUT_ONE_SECOND / 15);
290  }
291 
292  for(j=0;j<8;j++) // Scroll the LEDs up
293  {
294  uchLedStatus = 8 >> j;
295  XGpio_DiscreteWrite(pLED_GPIO, 1, uchLedStatus);
296  delay(ABOUT_ONE_SECOND / 15);
297  }
298  }
299 }
300 
301 void max_set_PMOD_port(int nPortNumber, u8 uchPortType)
316 {
317  if(nPortNumber>=0 && nPortNumber<=3)
318  {
319  g_auchPortType[nPortNumber]=uchPortType;
320  }
322  delay(ABOUT_ONE_SECOND / 10);
323 }
324 
325 void max_configure_PMOD_port(u8 uchPmodPortA, u8 uchPmodPortB, u8 uchPmodPortC, u8 uchPmodPortD)
344 {
345  u8 uchPmodPortSelectBits=0;
346  // The PMOD ports are configured with an 8 bit word sent to GPIO2
347  // Bits 1:0 are for port #A
348  // Bits 3:2 are for port #B
349  // Bits 5:4 are for port #C
350  // Bits 7:6 are for Port #D
351 
352  //S = 2'b00 => UART active (PMOD_PORT_TYPE_UART)
353  //S = 2'b01 => SPI active (PMOD_PORT_TYPE_SPI)
354  //S = 2'b10 => GPIO active (PMOD_PORT_TYPE_GPIO)
355  //S = 2'b11 => I2C active (PMOD_PORT_TYPE_I2C)
356 
357  uchPmodPortSelectBits = (uchPmodPortD << 6) + (uchPmodPortC << 4) + (uchPmodPortB << 2) + uchPmodPortA;
358  XGpio_DiscreteWrite(&g_xGpioPmodPortMuxIO, 1, uchPmodPortSelectBits);
359 }
360 
361 int number_raised_to_power(int nBase, int nExponent)
373 {
374  int i=0;
375  int nValue=0;
376  if(nExponent==0)
377  nValue=1;
378  else
379  {
380  nValue = nBase;
381  for(i=1;i<nExponent;i++)
382  {
383  nValue = nValue * nBase;
384  }
385  }
386  return(nValue);
387 }
388 
389 int receive_byte_with_timeout(u32 unUartAddress, int nTimeoutInTenthsOfSeconds, u8 *uchRxData)
399 {
400  int j=0;
401  int nReturnVal = TRUE;
402  u8 uchInput = 0;
403 
404  // Check if there is a character in the UART Rx buffer
405  // Continue checking every 10th of a second for nTimeoutInSeconds
406  while(checkUartEmpty(unUartAddress) && (j < nTimeoutInTenthsOfSeconds))
407  {
408  j++;
410  }
411 
412  if(checkUartEmpty(unUartAddress))
413  nReturnVal = FALSE;
414  else
415  {
416  uchInput = getUartByte(unUartAddress);
417  // Check if it is an escape sequence
418  if(uchInput==27) // Escape sequence (likely an arrow key)
419  {
420  if(checkUartEmpty(unUartAddress))
421  nReturnVal = FALSE;
422  else
423  {
424  uchInput = getUartByte(unUartAddress);
425  if(uchInput==91) // Left bracket (part #2 of the 3 part escape sequence)
426  {
427  if(checkUartEmpty(unUartAddress))
428  nReturnVal = FALSE;
429  else
430  {
431  uchInput = getUartByte(unUartAddress);
432  if(uchInput==75)
433  uchInput = 244; // We have defined KEYPRESS_END as 244
434  }
435  }
436  }
437 
438  }
439  *uchRxData = uchInput;
440  nReturnVal = TRUE;
441  }
442  return(nReturnVal);
443 }
444 
445 int GetLine( char* sInputString, unsigned int unMaxSize )
456 {
457  u8 uchInputChar = 0;
458  unsigned int unInputStringIndex = 0;
459 
461  while( (uchInputChar != '\r') && (uchInputChar != '\n') && (unInputStringIndex < unMaxSize-1) )
462  {
463  sInputString[ unInputStringIndex ] = (char)uchInputChar;
464  unInputStringIndex++;
466  }
467  sInputString[ unInputStringIndex ] = '\0';
468 
469  return (unInputStringIndex < unMaxSize) ? unInputStringIndex : -1;
470 }
471 
472 void sendOLEDSPI(u8 uchDataToWrite)
481 {
482  int i;
483 
484  for(i=7;i>=0;i--)
485  {
486  // Set the OLED_SDIN bit
487  if(((uchDataToWrite >> i) & 0x01)==0x01)
489  else
491  XGpio_DiscreteWrite(&g_structureOLED.xgpioPort, 1, g_structureOLED.portStatus);
492  delay(100);
493 
494  // Clock in the data via a rising edge of SCLK
496  XGpio_DiscreteWrite(&g_structureOLED.xgpioPort, 1, g_structureOLED.portStatus);
497  delay(100);
499  XGpio_DiscreteWrite(&g_structureOLED.xgpioPort, 1, g_structureOLED.portStatus);
500  delay(100);
501  }
502 }
503 
504 void initializeOLED(u8 *pFont)
513 {
514  // First, initialize the global structure that represents the OLED device
515 
516  //GPIO that manages the bit-banged SPI interface to the OLED
517  //XGpio_Initialize(&g_structureOLED.xgpioPort, XPAR_AXI_GPIO_OLED_DEVICE_ID);
518  XGpio_Initialize(&g_structureOLED.xgpioPort, XPAR_AXI_GPIO_OLED_DEVICE_ID);
519  XGpio_SetDataDirection(&g_structureOLED.xgpioPort, 1, 0x00); // Set the OLED peripheral to outputs
520  XGpio_DiscreteWrite(&g_structureOLED.xgpioPort, 1, 0x00); // Set all values to zero
521  delay(100);
522 
523  // Set the font in the OLED structure
524  g_structureOLED.font = pFont;
525 
526  // Init the global variable that represents the OLED bit-bang pins
528 
529  // Init and clear the display buffer and the invertered/flipped buffer
532 
533  // Now, Initialize the OLED display (hardware)
534 
535  // Disable VBAT power supply to the OLED integrated switcher
536  // Note: These bits control the Gate voltage on a P-Channel MOSFET
538  XGpio_DiscreteWrite(&g_structureOLED.xgpioPort, 1, g_structureOLED.portStatus); // Set all values to zero
540 
541  //Enable VDD power supply to digital logic within OLED
543  XGpio_DiscreteWrite(&g_structureOLED.xgpioPort, 1, g_structureOLED.portStatus); // Set all values to zero
545 
546  // Disable reset
548  XGpio_DiscreteWrite(&g_structureOLED.xgpioPort, 1, g_structureOLED.portStatus); // Set all values to zero
550 
551  // Set Display Off
552  sendOLEDSPI(0xAE);
553  delay(100);
554 
555  // Set Display Clock Divide Ratio. Oscillator Frequency
556  sendOLEDSPI(0xD5);
557  delay(100);
558  sendOLEDSPI(0x80);
559  delay(100);
560 
561  // Set Multiplex Ratio
562  sendOLEDSPI(0xA8);
563  delay(100);
564  sendOLEDSPI(0x1F);
565  delay(100);
566 
567  // Set Display Offset
568  sendOLEDSPI(0xD3);
569  delay(100);
570  sendOLEDSPI(0x00);
571  delay(100);
572 
573  // Set Display Start Line
574  sendOLEDSPI(0x40);
575  delay(100);
576 
577  // Set Charge Pump
578  sendOLEDSPI(0x8D);
579  delay(100);
580  sendOLEDSPI(0x14);
581  delay(100);
582 
583  // Set Segment Re-Map
584  sendOLEDSPI(0xA1);
585  delay(100);
586 
587  // Set COM Output Scan Direction
588  sendOLEDSPI(0xC8);
589  delay(100);
590 
591  // Set Com Pins Hardware Configuration
592  sendOLEDSPI(0xDA);
593  delay(100);
594  sendOLEDSPI(0x02);
595  delay(100);
596 
597  // Set Contrast Control
598  sendOLEDSPI(0x81);
599  delay(100);
600  sendOLEDSPI(0x8F);
601  delay(100);
602 
603  // Set Pre-Charge Period
604  sendOLEDSPI(0xD9);
605  delay(100);
606  sendOLEDSPI(0xF1);
607  delay(100);
608 
609  // Set VCOMH Deselect Level
610  sendOLEDSPI(0xDB);
611  delay(100);
612  sendOLEDSPI(0x40);
613  delay(100);
614 
615  // Set Entire Display On
616  sendOLEDSPI(0xA4);
617  delay(100);
618 
619  // Set Normal/Inverse Display
620  sendOLEDSPI(0xA6);
621  delay(100);
622 
623  // Enable the VBAT power supply (which is used for the OLED)
625  XGpio_DiscreteWrite(&g_structureOLED.xgpioPort, 1, g_structureOLED.portStatus); // Set all values to zero
626  delay(ABOUT_ONE_SECOND/2); // Long delay for internal OLED switcher to stabilize
627 
628  // Set Display On
629  sendOLEDSPI(0xAF);
630  delay(100);
631 }
632 
633 void clearOLEDBuffer(u8 *pauchBuffer)
642 {
643  int i;
644 
645  for(i=0;i<512;i++)
646  pauchBuffer[i] = 0x00;
647 
648 }
649 
650 void displayOLEDBuffer(u8 *pauchBuffer)
660 {
661  int column=0;
662  int page=0;
663  u8 *p;
664  u8 uchPixelValue=0;
665 
666  // Set the display mode to page based transfers
667  sendOLEDSPI(0x20);
668  delay(100);
669  sendOLEDSPI(0x02);
670  delay(100);
671 
672  // Set the page pointer lower nibble to 0x0
673  sendOLEDSPI(0x00);
674  delay(100);
675 
676  // Set the page pointer upper nibble to 0x0
677  sendOLEDSPI(0x10);
678  delay(100);
679 
680  // Write 4 pages worth of data
681  // Note that the SSD1306 controller can handle 128x64 displays, but the OLED
682  // used on zedboard is only 128x32. Data is provided to the display as (4) pages of 128 bytes each.
683  p = pauchBuffer;
684  for(page=0;page<4;page++)
685  {
686  // Enable Command Mode (shut off data mode)
688  XGpio_DiscreteWrite(&g_structureOLED.xgpioPort, 1, g_structureOLED.portStatus); // Set all values to zero
689  delay(100); // Long delay for internal OLED switcher to stabilize
690 
691  // Set the page command by issuing 0xB0 (page0), 0xB1 (page1) etc.
692  sendOLEDSPI((0xB0+page));
693 
694  // Enable the Data mode (shut off command mode)
696  XGpio_DiscreteWrite(&g_structureOLED.xgpioPort, 1, g_structureOLED.portStatus); // Set all values to zero
697  delay(100); // Long delay for internal OLED switcher to stabilize
698 
699  for(column=0;column<128;column++)
700  {
701  uchPixelValue = *p;
702  sendOLEDSPI(uchPixelValue); // change this to zero
703  p++;
704  }
705  }
706 
707  // Enable Command Mode (shut off data mode)
709  XGpio_DiscreteWrite(&g_structureOLED.xgpioPort, 1, g_structureOLED.portStatus); // Set all values to zero
710  delay(100); // Long delay for internal OLED switcher to stabilize
711 }
712 
713 void putCharOLED(int x, int y, char chCharacter)
724 {
725  int i;
726  int nDisplayBufferIndex=0;
727  int nFontIndex=0;
728 
729  // Create the index location for the character into the display memory
730  nDisplayBufferIndex = (x * 8) + (y * 16 * 8);
731 
732  // Make sure the character has a valid value, else ignore
733  if(chCharacter >=0 && chCharacter<128)
734  {
735  nFontIndex = chCharacter * 8;
736 
737  for(i=nDisplayBufferIndex;i<nDisplayBufferIndex+8;i++)
738  {
740  nFontIndex++;
741  }
742  }
743 }
744 
745 void printfToBufferOLED(int x, int y,char *chString)
756 {
757  int nStringLength;
758  int nInitialDisplayLocation;
759  int nRemainingDisplayLength;
760  int i;
761  int xIndex=0;
762  int yIndex=0;
763  nStringLength = strlen(chString);
764 
765  // Will the string fit on the display? If not, truncate the length
766  nInitialDisplayLocation = y*16 + x;
767  nRemainingDisplayLength = 64 - nInitialDisplayLocation;
768  if(nStringLength > nRemainingDisplayLength)
769  nStringLength = nRemainingDisplayLength;
770 
771  xIndex = x;
772  yIndex = y;
773  for(i=0;i<nStringLength;i++)
774  {
775  putCharOLED(xIndex,yIndex,chString[i]);
776  xIndex++;
777  if(xIndex==16)
778  {
779  xIndex=0;
780  yIndex++;
781  }
782  }
783 }
784 
785 void printfToOLED(int x, int y,char *chString)
797 {
798  printfToBufferOLED(x,y,chString);
801 }
802 
803 
804 void flipAndCopyDisplayBuffer(u8 *pauchSourceBuffer, u8 *pauchDestinationBuffer)
815 {
816  int i,x,y;
817  u8 uchTempWord1;
818  u8 uchTempWord2;
819  u8 uchTempWord3;
820 
821  for(y=0;y<4;y++)
822  {
823  for(x=0;x<128;x++)
824  {
825  uchTempWord1 = pauchSourceBuffer[511-((y*128)+x)];
826  uchTempWord3 = 0;
827  for(i=0;i<8;i++)
828  {
829  uchTempWord2 = (uchTempWord1 >> (7-i)) & 0x01; // shift the bit to the bit0 location and mask off
830  uchTempWord2 = uchTempWord2 << i; // shift the bit back to the desired location.
831  uchTempWord3 += uchTempWord2;
832  }
833  pauchDestinationBuffer[((y*128)+x)] = uchTempWord3;
834  }
835  }
836 }
837 
838