C program

profilehzxlove
Lab1.zip

part1.c

// **** Include libraries here **** // Standard libraries #include <stdio.h> #include <stdlib.h> //Class specific libraries #include "BOARD.h" // Microchip libraries #include <xc.h> // User libraries int main(void) { BOARD_Init(); unsigned char vals[] = { rand(), rand(), rand(), rand(), rand() }; int valsToBeSorted[] = {vals[0], vals[1], vals[2], vals[3], vals[4]}; // Sort the array in place. int i, j; for (i = 0; i < 5; i++) { int aTemp = valsToBeSorted[i]; for (j = i - 1; j >= 0; j--) { if (valsToBeSorted[j] <= aTemp) break; valsToBeSorted[j + 1] = valsToBeSorted[j]; } valsToBeSorted [j+1] = aTemp; } // Print out the array printf("["); for (i=0;i<4;i++) { printf("%d, ", valsToBeSorted[i]); } printf("%d]\n", valsToBeSorted[i]); /* * Returning from main() is bad form in embedded environments. So we * sit and spin. */ while (1); }

part2.c

// **** Include libraries here **** // Standard libraries #include <stdio.h> //Class specific libraries #include "BOARD.h" // Microchip libraries #include <xc.h> // User libraries #include <stdio.h> #include <stdlib.h> int main(void) { BOARD_Init(); /*************************************************************************************************** * Your code goes in between this comment and the following one with asterisks. **************************************************************************************************/ /*************************************************************************************************** * Your code goes in between this comment and the preceding one with asterisks. **************************************************************************************************/ // Returning from main() is bad form in embedded environments. So we sit and spin. while (1); }

part3.c

// **** Include libraries here **** // Standard libraries #include <stdio.h> #include <math.h> //CMPE13 Support Library #include "BOARD.h" // Microchip libraries #include <xc.h> #include <plib.h> // User libraries // **** Set macros and preprocessor directives **** // **** Define global, module-level, or external variables here **** // **** Declare function prototypes **** #define QX 1.5 #define QY 2.8 #define PX -2.3 #define PY 8.6 #define DX (QX-PX) #define DY (QY-PY) int main() { BOARD_Init(); { /******************************** Your custom code goes below here *******************************/ double mathHypot=hypotf(DX,DY); printf("Hypot returned %f and should return %f\r\n",mathHypot,6.9340); double mathAtan2=atan2(QX,QY); printf("Atan2 returned %f and should return %f\r\n",mathAtan2,.4918); /*************************************************************************************************/ // You can never return from main() in an embedded system (one that lacks an operating system). // This will result in the processor restarting, which is almost certainly not what you want! while (1); } }

Ascii.h

#ifndef ASCII_H #define ASCII_H #include <stdint.h> // Specify the height and width of the characters defined in this library. #define ASCII_FONT_HEIGHT 8 #define ASCII_FONT_WIDTH 6 /** * Pack a font for most of the standard ASCII characters into a byte array. Each character is stored * as ASCII_FONT_WIDTH number of bytes which each byte corresponding to a vertical line of 8 pixels * on the display. * * Some extended ASCII characters are supported: * 0xF8: Degree symbol * * Some custom characters have also been implemented in lieu of some non-printing characters: * 0x01: Top of oven, on * 0x02: Top of oven, off * 0x03: Bottom of oven, on * 0x04: Bottom of oven, off */ extern const uint8_t ascii[256][ASCII_FONT_WIDTH]; #endif // ASCII_H

Ascii.c

#include "Ascii.h" /* * This file defines a bitmap font corresponding to the standard ASCII character set (0-7F). */ const unsigned char ascii[256][6] = { // Non-printing characters 0x00 - 0x1F {0,0,0,0,0,0}, { // top of oven, on (0x01) 0b00000101, 0b11110011, 0b00000101, 0b11110011, 0b00000101, 0b11110011 }, { // top of oven, off (0x02) 0b00000101, 0b00000011, 0b00000101, 0b00000011, 0b00000101, 0b00000011 }, { // bottom of oven, on (0x03) 0b10100000, 0b11001111, 0b10100000, 0b11001111, 0b10100000, 0b11001111 }, { // bottom of oven, off (0x04) 0b10100000, 0b11000000, 0b10100000, 0b11000000, 0b10100000, 0b11000000 },{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, { // (space) 0x20 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000 }, { // ! 0x21 0b00000000, 0b00000000, 0b01011110, 0b00000000, 0b00000000, 0b00000000 }, { // " 0x22 0b00001100, 0b00000010, 0b00000000, 0b00001100, 0b00000010, 0b00000000 }, { // # 0x23 0b00010100, 0b01111111, 0b00010100, 0b01111111, 0b00010100, 0b00000000 }, { // $ 0x24 0b00100100, 0b00101010, 0b01111111, 0b00101010, 0b00010010, 0b00000000 }, { // % 0x25 0b00100011, 0b00010011, 0b00001000, 0b01100100, 0b01100010, 0b00000000 }, { // & 0x26 0b00110110, 0b01001001, 0b01010001, 0b00100010, 0b01010000, 0b00000000 }, { // ' 0x27 0b00000000, 0b00000000, 0b00001100, 0b00000010, 0b00000000, 0b00000000 }, { // ( 0x28 0b00000000, 0b00000000, 0b00111110, 0b01000001, 0b00000000, 0b00000000 }, { // ) 0x29 0b00000000, 0b01000001, 0b00111110, 0b00000000, 0b00000000, 0b00000000 }, { // * 0x2A 0b00001010, 0b00000100, 0b00011111, 0b00000100, 0b00001010, 0b00000000 }, { // + 0x2B 0b00001000, 0b00001000, 0b00111110, 0b00001000, 0b00001000, 0b00000000 }, { // , 0x2C 0b00000000, 0b00000000, 0b01010000, 0b00110000, 0b00000000, 0b00000000 }, { // - 0x2D 0b00001000, 0b00001000, 0b00001000, 0b00001000, 0b00001000, 0b00000000 }, { // . 0x2E 0b00000000, 0b01100000, 0b01100000, 0b00000000, 0b00000000, 0b00000000 }, { // / 0x2F 0b01000000, 0b00110000, 0b00001000, 0b00000110, 0b00000001, 0b00000000 }, { // 0 0x30 0b00111110, 0b01010001, 0b01001001, 0b01000101, 0b00111110, 0b00000000 }, { // 1 0x31 0b01000010, 0b01000010, 0b01111111, 0b01000000, 0b01000000, 0b00000000 }, { // 2 0x32 0b01000110, 0b01100001, 0b01010001, 0b01001001, 0b01000110, 0b00000000 }, { // 3 0x33 0b00100010, 0b01000001, 0b01001001, 0b01001001, 0b00110110, 0b00000000 }, { // 4 0x34 0b00011000, 0b00010100, 0b00010010, 0b01111111, 0b00010000, 0b00000000 }, { // 5 0x35 0b01001111, 0b01001001, 0b01001001, 0b01001001, 0b00110001, 0b00000000 }, { // 6 0x36 0b00111100, 0b01001010, 0b01001001, 0b01001001, 0b00110000, 0b00000000 }, { // 7 0x37 0b00000001, 0b01110001, 0b00001001, 0b00000101, 0b00000011, 0b00000000 }, { // 8 0x38 0b00110110, 0b01001001, 0b01001001, 0b01001001, 0b00110110, 0b00000000 }, { // 9 0x39 0b00000110, 0b01001001, 0b01001001, 0b00101001, 0b00011110, 0b00000000 }, { // : 0x3A 0b00000000, 0b00000000, 0b00110110, 0b00110110, 0b00000000, 0b00000000 }, { // ; 0x3B 0b00000000, 0b00000000, 0b01010110, 0b00110110, 0b00000000, 0b00000000 }, { // < 0x3C 0b00001000, 0b00010100, 0b00100010, 0b01000001, 0b00000000, 0b00000000 }, { // = 0x3D 0b00010100, 0b00010100, 0b00010100, 0b00010100, 0b00010100, 0b00000000 }, { // > 0x3E 0b00000000, 0b01000001, 0b00100010, 0b00010100, 0b00001000, 0b00000000 }, { // ? 0x3F 0b00000110, 0b00000001, 0b01010001, 0b00001001, 0b00000110, 0b00000000 }, { // @ 0x40 0b00111110, 0b01000001, 0b01011101, 0b01010101, 0b00111110, 0b00000000 }, { // A 0x41 0b01111110, 0b00001001, 0b00001001, 0b00001001, 0b01111110, 0b00000000 }, { // B 0x42 0b01111111, 0b01001001, 0b01001001, 0b01001001, 0b00110110, 0b00000000 }, { // C 0x43 0b00111110, 0b01000001, 0b01000001, 0b01000001, 0b01000001, 0b00000000 }, { // D 0x44 0b01111111, 0b01000001, 0b01000001, 0b01000001, 0b00111110, 0b00000000 }, { // E 0x45 0b01111111, 0b01001001, 0b01001001, 0b01001001, 0b01000001, 0b00000000 }, { // F 0x46 0b01111111, 0b00001001, 0b00001001, 0b00001001, 0b00000001, 0b00000000 }, { // G 0x47 0b00111110, 0b01000001, 0b01000001, 0b01001001, 0b00111001, 0b00000000 }, { // H 0x48 0b01111111, 0b00001000, 0b00001000, 0b00001000, 0b01111111, 0b00000000 }, { // I 0x49 0b01000001, 0b01000001, 0b01111111, 0b01000001, 0b01000001, 0b00000000 }, { // J 0x4A 0b00110001, 0b01000001, 0b01000001, 0b00111111, 0b00000001, 0b00000000 }, { // K 0x4B 0b01111111, 0b00001000, 0b00001000, 0b00010100, 0b01100011, 0b00000000 }, { // L 0x4C 0b01111111, 0b01000000, 0b01000000, 0b01000000, 0b01000000, 0b00000000 }, { // M 0x4D 0b01111111, 0b00000010, 0b00001100, 0b00000010, 0b01111111, 0b00000000 }, { // N 0x4E 0b01111111, 0b00000100, 0b00001000, 0b00010000, 0b01111111, 0b00000000 }, { // O 0x4F 0b00111110, 0b01000001, 0b01000001, 0b01000001, 0b00111110, 0b00000000 }, { // P 0x50 0b01111111, 0b00001001, 0b00001001, 0b00001001, 0b00000110, 0b00000000 }, { // Q 0x51 0b00111110, 0b01000001, 0b01010001, 0b00100001, 0b01011110, 0b00000000 }, { // R 0x52 0b01111111, 0b00001001, 0b00001001, 0b00001001, 0b01110110, 0b00000000 }, { // S 0x53 0b01000110, 0b01001001, 0b01001001, 0b01001001, 0b00110001, 0b00000000 }, { // T 0x54 0b00000001, 0b00000001, 0b01111111, 0b00000001, 0b00000001, 0b00000000 }, { // U 0x55 0b00111111, 0b01000000, 0b01000000, 0b01000000, 0b00111111, 0b00000000 }, { // V 0x56 0b00011111, 0b00100000, 0b01000000, 0b00100000, 0b00011111, 0b00000000 }, { // W 0x57 0b00111111, 0b01000000, 0b00110000, 0b01000000, 0b00111111, 0b00000000 }, { // X 0x58 0b01100011, 0b00010100, 0b00001000, 0b00010100, 0b01100011, 0b00000000 }, { // Y 0x59 0b00000111, 0b00001000, 0b01110000, 0b00001000, 0b00000111, 0b00000000 }, { // Z 0x5A 0b01100001, 0b01010001, 0b01001001, 0b01000101, 0b01000011, 0b00000000 }, { // [ 0x5B 0b00000000, 0b01111111, 0b01000001, 0b01000001, 0b00000000, 0b00000000 }, { // \ 0x5C 0b00000001, 0b00000110, 0b00001000, 0b00110000, 0b01000000, 0b00000000 }, { // ] 0x5D 0b00000000, 0b01000001, 0b01000001, 0b01111111, 0b00000000, 0b00000000 }, { // ^ 0x5E 0b00000100, 0b00000010, 0b00000001, 0b00000010, 0b00000100, 0b00000000 }, { // _ 0x5F 0b01000000, 0b01000000, 0b01000000, 0b01000000, 0b01000000, 0b00000000 }, { // ` 0x60 0b00000000, 0b00000001, 0b00000010, 0b00000100, 0b00000000, 0b00000000 }, { // a 0x61 0b00100000, 0b01010100, 0b01010100, 0b01010100, 0b01111000, 0b00000000 }, { // b 0x62 0b01111111, 0b01000100, 0b01000100, 0b01000100, 0b00111000, 0b00000000 }, { // c 0x63 0b00111000, 0b01000100, 0b01000100, 0b01000100, 0b01000100, 0b00000000 }, { // d 0x64 0b00111000, 0b01000100, 0b01000100, 0b01000100, 0b01111111, 0b00000000 }, { // e 0x65 0b00111000, 0b01010100, 0b01010100, 0b01010100, 0b01011000, 0b00000000 }, { // f 0x66 0b00001000, 0b01111110, 0b00001001, 0b00001001, 0b00000010, 0b00000000 }, { // g 0x67 0b00001000, 0b01010100, 0b01010100, 0b01010100, 0b00111000, 0b00000000 }, { // h 0x68 0b01111111, 0b00000100, 0b00000100, 0b00000100, 0b01111000, 0b00000000 }, { // i 0x69 0b00000000, 0b01001000, 0b01111010, 0b01000000, 0b00000000, 0b00000000 }, { // j 0x6A 0b00100000, 0b01000000, 0b01000000, 0b00111010, 0b00000000, 0b00000000, }, { // k 0x6B 0b01111111, 0b00010000, 0b00010000, 0b00101000, 0b01000100, 0b00000000 }, { // l 0x6C 0b00000000, 0b00000001, 0b01111111, 0b01000000, 0b00000000, 0b00000000 }, { // m 0x6D 0b01111100, 0b00000100, 0b01111000, 0b00000100, 0b01111100, 0b00000000 }, { // n 0x6E 0b01111100, 0b00001000, 0b00000100, 0b00000100, 0b01111000, 0b00000000 }, { // o 0x6F 0b00111000, 0b01000100, 0b01000100, 0b01000100, 0b00111000, 0b00000000 }, { // p 0x70 0b11111100, 0b00100100, 0b00100100, 0b00100100, 0b00011000, 0b00000000 }, { // q 0x71 0b00011000, 0b00100100, 0b00100100, 0b00100100, 0b11111100, 0b00000000 }, { // r 0x72 0b01111100, 0b00001000, 0b00000100, 0b00000100, 0b00000100, 0b00000000 }, { // s 0x73 0b01001000, 0b01010100, 0b01010100, 0b01010100, 0b00100100, 0b00000000 }, { // t 0x74 0b00000100, 0b00111110, 0b01000100, 0b01000100, 0b00000000, 0b00000000 }, { // u 0x75 0b00111100, 0b01000000, 0b01000000, 0b01000000, 0b00111100, 0b00000000 }, { // v 0x76 0b00011100, 0b00100000, 0b01000000, 0b00100000, 0b00011100, 0b00000000 }, { // w 0x77 0b00111100, 0b01000000, 0b00100000, 0b01000000, 0b00111100, 0b00000000 }, { // x 0x78 0b01000100, 0b00101000, 0b00010000, 0b00101000, 0b01000100, 0b00000000 }, { // y 0x79 0b00001100, 0b01010000, 0b01010000, 0b01010000, 0b00111100, 0b00000000 }, { // z 0x7A 0b01000100, 0b01100100, 0b01010100, 0b01001100, 0b01000100, 0b00000000 }, { // { 0x7B 0b00001000, 0b00001000, 0b00110110, 0b01000001, 0b00000000, 0b00000000 }, { // | 0x7C 0b00000000, 0b00000000, 0b01111111, 0b00000000, 0b00000000, 0b00000000 }, { // } 0x7D 0b00000000, 0b01000001, 0b00110110, 0b00001000, 0b00001000, 0b00000000 }, { // ~ 0x7E 0b00001000, 0b00000100, 0b00001000, 0b00001000, 0b00000100, 0b00000000 }, { // DEL 0x7F 0b00000000, 0b00010000, 0b00111000, 0b00010000, 0b00000000, 0b00000000 }, {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 131 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 135 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 139 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 143 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 147 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 151 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 155 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 159 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 163 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 167 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 171 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 175 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 179 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 183 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 187 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 191 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 195 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 199 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 203 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 207 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 211 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 215 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 219 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 223 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 227 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 231 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 235 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 239 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 243 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 247 { // degree 0xF8 (248) 0b00000000, 0b00000110, 0b00001001, 0b00001001, 0b00000110, 0b00000000 }, {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0}, // 251 {0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0},{0,0,0,0,0,0} // 255 };

BOARD.c

/* * File: BOARD.h * Author: Max Dunne * * Created on December 19, 2012, 2:08 PM * * Much of the odder code come directly from the microchip peripheral library as reinventing the wheel seemed * not necessary */ #include "BOARD.h" // Microchip Libraries #include <xc.h> #include <plib.h> #include <peripheral/osc.h> #include <peripheral/system.h> #include <stdint.h> #include <stdio.h> /******************************************************************************* * PRAGMAS * ******************************************************************************/ // Configuration Bits // SYSCLK = 80MHz // PBCLK = 20MHz // using POSC w/ PLL, XT mode #pragma config FPBDIV = DIV_4 #pragma config FPLLIDIV = DIV_2 // Set the PLL input divider to 2, seems to #pragma config IESO = OFF // Internal/External Switch #pragma config POSCMOD = XT // Primary Oscillator Configuration for XT osc mode #pragma config OSCIOFNC = OFF // Disable clock signal output #pragma config FCKSM = CSECMD // Clock Switching and Monitor Selection #pragma config WDTPS = PS1 // Specify the watchdog timer interval (unused) #pragma config FWDTEN = OFF // Disable the watchdog timer #pragma config ICESEL = ICS_PGx2 // Allow for debugging with the Uno32 #pragma config PWP = OFF // Keep the program flash writeable #pragma config BWP = OFF // Keep the boot flash writeable #pragma config CP = OFF // Disable code protect /******************************************************************************* * PRIVATE #DEFINES * ******************************************************************************/ #define SYSTEM_CLOCK 80000000L #define PB_CLOCK (SYSTEM_CLOCK / 4) #define QUEUESIZE 512 #define TurnOffAndClearInterrupt(Name) INTEnable(Name,INT_DISABLED); INTClearFlag(Name) #define TurnPortToInput(Tris) Tris=0xFFFF //#define LAB10_READ_OVERWRITE /******************************************************************************* * PRIVATE DATATYPES * ******************************************************************************/ /******************************************************************************* * PRIVATE FUNCTION PROTOTYPES * ******************************************************************************/ void SERIAL_Init(void); /******************************************************************************* * PRIVATE VARIABLES * ******************************************************************************/ /******************************************************************************* * PUBLIC FUNCTIONS * ******************************************************************************/ /** * Function: BOARD_Init(void) * @param None * @return None * @brief Initializes the board for 80MHz SYSCLK and 20MHz PBCLK. */ void BOARD_Init() { // Set the PB divider to its maximum before altering SYSCLK, ensure that PB limits are observed OSCSetPBDIV(OSC_PB_DIV_8); // Configure the system for the specified 80MHz clock // Changse the flash wait state, RAM wait state, and enable prefetch cache SYSTEMConfig(SYSTEM_CLOCK, SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE); // Configure for performance at 80MHz SYSTEMConfigPerformance(SYSTEM_CLOCK); // Use POSC, XT with PLL, XT specified above in config // PLL multiplier of 20 // PLL postdiv of 1 // FRC postdiv of 1, not using FRC so value is inconsequential OSCConfig(OSC_POSC_PLL, OSC_PLL_MULT_20, OSC_PLL_POST_1, OSC_FRC_POST_1); // Set PBCLK to 20MHz OSCSetPBDIV(OSC_PB_DIV_4); // Disable the secondary oscillator mOSCDisableSOSC(); //seeds the random number generator with the time char seed1[] = __TIME__; unsigned int seed2 = (((unsigned int) (seed1[7] ^ seed1[2])) << 8) | ((unsigned int) (seed1[4] ^ seed1[6])); srand(seed2); //enables the interrupt system in the new style //INTConfigureSystem(INT_SYSTEM_CONFIG_MULT_VECTOR); unsigned int val; // set the CP0 cause IV bit high asm volatile("mfc0 %0,$13" : "=r"(val)); val |= 0x00800000; asm volatile("mtc0 %0,$13" : "+r"(val)); INTCONSET = _INTCON_MVEC_MASK; //INTEnableInterrupts(); int status; asm volatile("ei %0" : "=r"(status)); // Initialize for serial SERIAL_Init(); } /** * Function: BOARD_End(void) * @param None * @return None * @brief shuts down all peripherals except for serial and A/D. Turns all pins * into input * @author Max Dunne, 2013.09.20 */ void BOARD_End() { // set all interrupt enable flags to zero IEC0 = 0; IEC1 = 0; //set all flags to zero IFS0 = 0; IFS1 = 0; // disable timer interrupts, clear flags and turn off module T1CON = 0; T2CON = 0; T3CON = 0; T4CON = 0; T5CON = 0; // disable input capture interrupts, clear flags and turn off module IC1CONCLR = _IC1CON_ICM_MASK; IC2CONCLR = _IC2CON_ICM_MASK; IC3CONCLR = _IC3CON_ICM_MASK; IC4CONCLR = _IC4CON_ICM_MASK; IC5CONCLR = _IC5CON_ICM_MASK; // disable output compare interrupts, clear flags and turn off module OC1CONCLR = _OC1CON_ON_MASK; OC2CONCLR = _OC2CON_ON_MASK; OC3CONCLR = _OC3CON_ON_MASK; OC4CONCLR = _OC4CON_ON_MASK; OC5CONCLR = _OC5CON_ON_MASK; // disable I2C interrupts, clear flags and turn off module I2C1CONCLR = _I2C1CON_ON_MASK; I2C2CONCLR = _I2C2CON_ON_MASK; //disable spi interrupts, clear flags and turn off module SPI1CONCLR = _SPI1CON_ON_MASK; SPI2CONCLR = _SPI2CON_ON_MASK; // disable external interrupts, clear flags and turn off module // set all ports to be digital inputs TurnPortToInput(TRISB); TurnPortToInput(TRISC); TurnPortToInput(TRISD); TurnPortToInput(TRISE); TurnPortToInput(TRISF); TurnPortToInput(TRISG); //Serial and A/D are left on for output and battery monitoring respectively } /** * Function: BOARD_GetPBClock(void) * @param None * @return */ unsigned int BOARD_GetPBClock() { return PB_CLOCK; } /** * Function: BOARD_GetSysClock(void) * @param None * @return */ unsigned int BOARD_GetSysClock() { return SYSTEM_CLOCK; } /******************************************************************************* * PRIVATE FUNCTIONS * ******************************************************************************/ /** * @Function SERIAL_Init(void) * @param none * @return none * @brief Initializes the UART subsystem to 115200 and sets up the circular buffer * @author Max Dunne, 2011.11.10 */ void SERIAL_Init(void) { // we first clear the Configs Register to ensure a blank state and peripheral is off. U1MODE = 0; U1STA = 0; //UARTConfigure(UART1, 0x00); //we then calculate the required frequency, note that this comes from plib source to avoid rounding errors int sourceClock = BOARD_GetPBClock() >> 3; int brg = sourceClock / 115200; brg++; brg >>= 1; brg--; U1BRG = brg; //UARTSetDataRate(UART1, PB_CLOCK, 115200); //UARTSetFifoMode(UART1, UART_INTERRUPT_ON_RX_NOT_EMPTY | UART_INTERRUPT_ON_RX_NOT_EMPTY); //we now enable the device U1STAbits.UTXEN = 1; U1STAbits.URXEN = 1; U1MODEbits.UARTEN = 1; //UARTEnable(UART1, UART_ENABLE_FLAGS(UART_PERIPHERAL | UART_TX | UART_RX)); __XC_UART = 1; //printf("\r\n%d\t%d",U1BRG,brg); } /******************************************************************************* * OVERRIDE FUNCTIONS * ******************************************************************************/ /** * @Function read(int handle, void *buffer, unsigned int len) * @param handle * @param buffer * @param len * @return Returns the number of characters read into buffer * @brief Overrides the built-in function called for scanf() to ensure proper functionality */ #ifndef LAB10_READ_OVERWRITE int read(int handle, void *buffer, unsigned int len) { int i; if (handle == 0) { while (!U1STAbits.URXDA) { if (U1STAbits.OERR) { U1STAbits.OERR = 0; } continue; } i = 0; while (U1STAbits.URXDA) { char tmp = U1RXREG; if (tmp == '\r') { tmp = '\n'; } *(char*) buffer++ = tmp; //WriteUART1(tmp); U1TXREG = tmp; i++; } return i; } return 0; } #endif #ifdef BOARD_TEST int main(void) { BOARD_Init(); printf("\r\nThis stub tests SERIAL Functionality with scanf"); printf("\r\nIt will intake integers and divide by 2"); printf("\r\n Peripheral Clock: %d", BOARD_GetPBClock()); printf("\r\n Peripheral Clock: %d\r\n", BOARD_GetSysClock()); char trash; int input; while (1) { scanf("%d%c", &input, &trash); printf("\r\nEntered: %d\t/2: %d\r\n", input, input / 2); } while (1); return 0; } #endif

BOARD.h

/* * File: BOARD.h * Author: Max Dunne * * Created on December 19, 2012, 2:08 PM */ #ifndef BOARD_H #define BOARD_H /******************************************************************************* * PUBLIC #INCLUDES * ******************************************************************************/ #include <GenericTypeDefs.h> #include <stdint.h> #include <xc.h> /******************************************************************************* * PUBLIC #DEFINES * ******************************************************************************/ //suppresses various warnings that we don't need to worry about for CMPE13 #ifndef _SUPPRESS_PLIB_WARNING #define _SUPPRESS_PLIB_WARNING #endif #ifndef _DISABLE_OPENADC10_CONFIGPORT_WARNING #define _DISABLE_OPENADC10_CONFIGPORT_WARNING #endif // Define some standard error codes. enum { SIZE_ERROR = -1, STANDARD_ERROR, SUCCESS }; // Specify the default UART to use. UART1 is selected the Uno32, as it's the one on the USB port. #define UART_USED UART1 // Set the baud rate for use with the UART. This is chosen as it's the default baud rate for Tera // Term. #define UART_BAUD_RATE 115200 /* * Set some helper macros for interfacing with the switches */ // Define macros for referring to the single-bit values of the switches. #define SW1 PORTDbits.RD8 #define SW2 PORTDbits.RD9 #define SW3 PORTDbits.RD10 #define SW4 PORTDbits.RD11 /** * Provides a way to quickly get the status of all 4 switches as a nibble, where a bit is 1 if * the button is being pressed and 0 if it's not. The buttons are ordered such that bit 3 is switch * 4 and bit 0 is switch 1. * @see enum ButtonStateFlags */ #define SWITCH_STATES() ((PORTD >> 8) & 0x0F) /** * The SwitchStateFlags enum provides a bitmask for use with the SWITCH_STATES macro. By bitwise- * ANDing any of these enum values with the return value from SWITCH_STATES, the current state of * the switches can be tested. * * For example: * * uint8_t switchesState = SWITCH_STATES(); * if (switchesState & SWITCH_STATE_SW3) { * // Switch 3 is on. * } * * @see SWITCH_STATES() */ enum SwitchStateFlags { SWITCH_STATE_SW1 = 0x1, SWITCH_STATE_SW2 = 0x2, SWITCH_STATE_SW3 = 0x4, SWITCH_STATE_SW4 = 0x8 }; /* * Set some helper macros for interfacing with the buttons */ // Define macros for referring to the single-bit values of the buttons. #define BTN1 PORTFbits.RF1 #define BTN2 PORTDbits.RD5 #define BTN3 PORTDbits.RD6 #define BTN4 PORTDbits.RD7 /** * Provides a way to quickly get the status of all 4 pushbuttons in to 4-bits, where a bit is 1 if * the button is being pressed and 0 if it's not. The buttons are ordered such that bit 3 is button * 4 and bit 0 is button 1. * @see enum ButtonStateFlags */ #define BUTTON_STATES() (((PORTD >> 4) & 0x0E) | ((PORTF >> 1) & 0x01)) /** * The ButtonStateFlags enum provides a bitmask for use with the BUTTON_STATES macro. By bitwise- * ANDing any of these enum values with the return value from BUTTON_STATES, the current state of * the buttons can be tested. * * For example: * * uint8_t buttonsState = BUTTON_STATES(); * if (buttonsState & BUTTON_STATE_3) { * // Buttons 3 is pressed down. * } * * @see BUTTON_STATES() */ enum ButtonStateFlags { BUTTON_STATE_1 = 0x1, BUTTON_STATE_2 = 0x2, BUTTON_STATE_3 = 0x4, BUTTON_STATE_4 = 0x8 }; /** * Enter an infinite loop and flash one of the status LEDs. This should be used when there is an * unrecoverable error onboard, like when a subsystem fails to initialize. */ #define FATAL_ERROR() do { \ TRISFCLR = 1; \ LATFCLR = 1; \ while (1) { \ unsigned long int i; \ for (i = 0; i < 600000; ++i); \ LATFINV = 1; \ } \ } while (0); /******************************************************************************* * PUBLIC FUNCTIONS * ******************************************************************************/ /** * Function: BOARD_Init(void) * @param None * @return None * @brief Set the clocks up for the board, initializes the serial port, and turns * on the A/D subsystem for battery monitoring * @author Max Dunne, 2013.09.15 */ void BOARD_Init(); /** * Function: BOARD_End(void) * @param None * @return None * @brief shuts down all peripherals except for serial and A/D. Turns all pins * into input * @author Max Dunne, 2013.09.20 */ void BOARD_End(); /** * Function: BOARD_GetPBClock(void) * @param None * @return PB_CLOCK - speed the peripheral clock is running in hertz * @brief returns the speed of the peripheral clock. Nominally at 20Mhz * @author Max Dunne, 2013.09.01 */ unsigned int BOARD_GetPBClock(); /** * Function: BOARD_GetSysClock(void) * @param None * @return SYS_CLOCK - speed the main clock is running at */ unsigned int BOARD_GetSysClock(); #endif /* BOARD_H */

Oled.h

#ifndef OLED_H #define OLED_H /** * This file provides a complete interface for interacting with the OLED on Digilent's I/O Shield. * It works by storing a backend array of pixel data for storing modifications and then flushing * that to the screen to update it when OledUpdate() is called. Since OledUpdate() is very slow, * this allows for batching together a lot of drawing operations before finally updating the screen * at the end in one go. * * This OLED is a monochrome display, offering black and white as your color options. These can be * specified as arguments to OledDrawChar() and OledClear(). Note that this coloring can be inverted * on the display itself by calling OledSetDisplayInverted(). This doesn't actually modify the data * stored in the pixels, but merely switches what colors each bit value represents. * * The OLED offers both a pixel interface and a text interface for drawing. Individual pixels can be * read and changed with the Oled*Pixel() functions. * * Higher-level text operations can be done through OledDrawChar() and OledDrawString, with the * latter function being the easier one to use. It allows for writing text across all OLED_NUM_LINES * lines on the display where each line can hold up to OLED_CHARS_PER_LINE complete characters. * * The font (defined in Ascii.h) used for drawing characters is a custom monospaced font. It * provides glyphs for most of the basic ASCII character set, but is incomplete. Additionally some * non-printing characters have been repurposed for custom characters for specific uses * (@see Ascii.h). */ #include "Ascii.h" #include "OledDriver.h" #include "BOARD.h" /** * Define constants for available colors for the OLED: either white or black. */ typedef enum { OLED_COLOR_BLACK = 0, OLED_COLOR_WHITE = 1 } OledColor; // Define how many lines of text the display can show. #define OLED_NUM_LINES (OLED_DRIVER_PIXEL_ROWS / ASCII_FONT_HEIGHT) // Define how many complete characters can be displayed on a row of text. #define OLED_CHARS_PER_LINE (OLED_DRIVER_PIXEL_COLUMNS / ASCII_FONT_WIDTH) /** * Initializes the OLED, turns it on, and clears the screen. */ void OledInit(void); /** * Sets a specific pixel in the frame buffer, available colors are black or white. * @note OledUpdate() must be called before the OLED will actually display these changes. * @param x The X position (left is zero) * @param y The Y position (top is zero) * @param color OLED_COLOR_WHITE or OLED_COLOR_BLACK */ void OledSetPixel(int x, int y, OledColor color); /** * Reads a pixel from the frame buffer. * @param x The X position (left is zero) * @param y The Y position (top is zero) * @return OLED_COLOR_WHITE or OLED_COLOR_BLACK */ int OledGetPixel(int x, int y); /** * Draws the specified character at the specified position, using Ascii.h as the font. * @note OledUpdate() must be called before the OLED will actually display these changes. * @param x The x-position to use as the left-most value for the character. * @param y The y-position to use as the top-most value for the character * @param c The character to write. Uses the character array defined in Ascii.h * @return True if the write succeeded. Fails on invalid inputs. */ uint8_t OledDrawChar(int x, int y, char c); /** * Draws a string to the screen buffer, starting on the top line. OLED_CHARS_PER_LINE characters fit * on each of the OLED_NUM_LINES lines on the screen. A newline in the string will start the * subsequent characters on the next line, otherwise once a line has run out of room no more * characters will display on the screen. There is no other special processing of the input string * besides this newline functionality, for example backspace characters just render as blank * characters. * * For example, the following code example shows Hello World I'm Working! on the OLED with each word * on its own line: * OledInit(); * OledDrawString("Hello\nWorldI'm\nWorking!\n"); * OledUpdate(); * * @note OledUpdate() must be called before the OLED will actually display these changes. * @param string A null-terminated string to print. */ void OledDrawString(const char *string); /** * Writes the specified color pixels to the entire frame buffer. * @note OledUpdate() must be called before the OLED will actually display these changes. * @param p The color to write all pixels in the OLED to. */ void OledClear(OledColor p); /** * Sets the display to display pixels the opposite color than what was intended. This does not * change the stored value for any pixel. * @see OledSetDisplayNormal */ void OledSetDisplayInverted(void); /** * Displays all pixels as they are stored, where a 0 indicates black and a 1 indicates white. This * is the default setting for the OLED on startup. This undoes `OledSetDisplayInverted()`. * @see OledSetDisplayInverted */ void OledSetDisplayNormal(void); /** * Turns on the OLED display. * @note This is not required as part of initialization, as `OledInit()` already does this. */ void OledOn(void); /** * Turns off the OLED display. * @note This is not required as part of initialization, as `OledInit()` already does this. */ void OledOff(void); /** * Refreshes the OLED display to reflect any changes. Should be called after any operation that * changes the display: OledSetPixel(), OledDrawChar(), OledDrawString(), and OledClear(). * * This function is very slow and so shouldn't be called too often or the OLED might look dim or * even show no data at all. This is because it uses a blocking SPI interface to push out the entire * screen of pixel data every time it's called. Like I said, very slow function! * * For example, the following code example shows Hello World I'm Workin! on the OLED with each word * on its own line: * OledInit(); * OledDrawString("Hello\nWorldI'm\nWorking!\n"); * OledUpdate(); */ void OledUpdate(void); #endif

OledDriver.h

#ifndef OLED_DRIVER_H #define OLED_DRIVER_H // Include standard C libraries. #include <stdint.h> // Include Microchip C libraries. #include <xc.h> /** * Configure the port and pins for each of the 4 control signals used with the OLED: * * F6: Controls the power to the controller logic. Active-low, so a 0 powers it on. * * F5: Controls the power to the OLED display. Active-low, so a 0 powers it on. * * F4: Sets the input mode of the controller logic. High indicates incoming data is display * data, while low indicates they're commands. * * G9: Reset pin connected to the display controller. Active-low, so a 0 holds the logic in * reset. */ #define OLED_DRIVER_CNTLR_POWER_PORT IOPORT_F #define OLED_DRIVER_CNTLR_POWER_BIT BIT_6 #define OLED_DRIVER_OLED_POWER_PORT IOPORT_F #define OLED_DRIVER_OLED_POWER_BIT BIT_5 #define OLED_DRIVER_MODE_PORT IOPORT_F #define OLED_DRIVER_MODE_BIT BIT_4 #define OLED_DRIVER_RESET_PORT IOPORT_G #define OLED_DRIVER_RESET_BIT BIT_9 // Set the SPI channel to use to communicate with the OLED. #define OLED_DRIVER_SPI_CHANNEL SPI_CHANNEL2 // The number of pixel columns in the OLED display. #define OLED_DRIVER_PIXEL_COLUMNS 128 // The number of pixel rows in the OLED display. #define OLED_DRIVER_PIXEL_ROWS 32 // Store how high each column is for the OLED in bits in terms of data structure storage. #define OLED_DRIVER_BUFFER_LINE_HEIGHT 8 // The number of bytes required to store all the data for the whole display. 1 bit / pixel. #define OLED_DRIVER_BUFFER_SIZE ((OLED_DRIVER_PIXEL_COLUMNS * OLED_DRIVER_PIXEL_ROWS) / 8) /** * This array is the off-screen frame buffer used for rendering. It isn't possible to read back from * the OLED display device, so display data is rendered into this off-screen buffer and then copied * to the display. The high-order bits equate to the lower pixel rows. * @note Any time this is updated, An `OledDriverUpdateDisplay()` call must be performed. */ extern uint8_t rgbOledBmp[OLED_DRIVER_BUFFER_SIZE]; /** * Initialize the PIC32MX to communicate with the UG-23832HSWEG04 OLED display through the SSD1306 * display controller. */ void OledHostInit(void); /** * Initialize the OLED display and driver circuitry. */ void OledDriverInitDisplay(void); /** * Disable the Oled display before power-off. This means powering it up, sending the display off * command, and finally disabling Vbat. */ void OledDriverDisableDisplay(void); /** * Update the display with the contents of rgb0ledBmp. */ void OledDriverUpdateDisplay(void); /** * Set the LCD to display pixel values as the opposite of how they are actually stored in NVRAM. So * pixels set to black (0) will display as white, and pixels set to white (1) will display as black. */ void OledDriverSetDisplayInverted(void); /** * Set the LCD to display pixel values normally, where a 1 indicates white and a 0 indicates black. * This is the default operating mode of the LCD and the mode it starts up in. */ void OledDriverSetDisplayNormal(void); #endif // OLED_DRIVER_H

Oled.c

#include <stddef.h> #include "OledDriver.h" #include "Oled.h" #include "Ascii.h" // in simulator we do nothing with the hardware, printing instead void OledInit(void) { #ifndef __MPLAB_DEBUGGER_SIMULATOR // First initialize the PIC32 to be able to talk over SPI to the OLED. OledHostInit(); // Now send initialization commands to the OLED. OledDriverInitDisplay(); // Clear the frame buffer by filling it with black pixels. OledClear(OLED_COLOR_BLACK); // Finally update the screen, triggering a write of all black pixels to the screen. OledUpdate(); #endif } void OledSetPixel(int x, int y, OledColor color) { #ifndef __MPLAB_DEBUGGER_SIMULATOR // Check for valid inputs before doing anything. if (x >= OLED_DRIVER_PIXEL_COLUMNS || y >= OLED_DRIVER_PIXEL_ROWS || x < 0 || y < 0) { return; } // Map the x/y coordinates into a byte/bit index. unsigned int index = ((y & 0xFFF8) << 4) + x; unsigned int shift = y & 0x0007; // Now set the pixel to the proper color, doing nothing if an invalid color was specified. if (color == OLED_COLOR_WHITE) { rgbOledBmp[index] = rgbOledBmp[index] | (1 << shift); } else if (color == OLED_COLOR_BLACK) { rgbOledBmp[index] = rgbOledBmp[index] & ~(1 << shift); } else { return; } #endif } int OledGetPixel(int x, int y) { #ifndef __MPLAB_DEBUGGER_SIMULATOR // Check for valid inputs before doing anything. if (x >= OLED_DRIVER_PIXEL_COLUMNS || y >= OLED_DRIVER_PIXEL_ROWS || x < 0 || y < 0) { return OLED_COLOR_BLACK; } // Map the x/y coordinates into a byte/bit index. unsigned int index = ((y & 0xFFF8) << 4) + x; unsigned int shift = y & 0x0007; // Now return the desired bit. return (rgbOledBmp[index] >> shift) & 0x01; #else return OLED_COLOR_BLACK; #endif } //in simulator this is the same as putchar uint8_t OledDrawChar(int x, int y, char c) { #ifndef __MPLAB_DEBUGGER_SIMULATOR if (x <= OLED_DRIVER_PIXEL_COLUMNS - ASCII_FONT_WIDTH && y <= OLED_DRIVER_PIXEL_ROWS - ASCII_FONT_HEIGHT) { // We need to convert our signed char into an unsigned value to index into the ascii[] array. int charIndex = (int) (unsigned char) c; // Now first determine the columns and rows of the OLED bits that need to be modified int rowMin, rowMax, colMin, colMax; rowMin = y / ASCII_FONT_HEIGHT; int rowY = y % ASCII_FONT_HEIGHT; rowMax = (y + ASCII_FONT_HEIGHT) / OLED_DRIVER_BUFFER_LINE_HEIGHT; colMin = x; colMax = x + ASCII_FONT_WIDTH; { // Generate a positive mask for where in the column the new symbol will be drawn. int colMask = ((1 << ASCII_FONT_HEIGHT) - 1) << rowY; int j; for (j = 0; j < colMax - colMin; ++j) { int oledCol = colMin + j; uint8_t newCharCol = rgbOledBmp[rowMin * OLED_DRIVER_PIXEL_COLUMNS + oledCol] & ~colMask; // Make sure we always grab from the top part of the character. newCharCol |= (ascii[charIndex][j] & (colMask >> rowY)) << rowY; rgbOledBmp[rowMin * OLED_DRIVER_PIXEL_COLUMNS + oledCol] = newCharCol; } } if (rowMax > rowMin) { // Generate a positive mask for where in the column the new symbol will be drawn. // Since we need the lower portion of the symbol, we recalculate its height. int colMask = ((1 << ASCII_FONT_HEIGHT) - 1) >> (OLED_DRIVER_BUFFER_LINE_HEIGHT - rowY); int j; for (j = 0; j < colMax - colMin; ++j) { int oledCol = colMin + j; uint8_t newCharCol = rgbOledBmp[rowMax * OLED_DRIVER_PIXEL_COLUMNS + oledCol] & ~colMask; // Make sure we grab the proper part of the character from the font. newCharCol |= (ascii[charIndex][j] & (colMask << (OLED_DRIVER_BUFFER_LINE_HEIGHT - rowY))) >> (OLED_DRIVER_BUFFER_LINE_HEIGHT - rowY); rgbOledBmp[rowMax * OLED_DRIVER_PIXEL_COLUMNS + oledCol] = newCharCol; } } } #else putchar(c); #endif return FALSE; } void OledDrawString(const char *string) { #ifndef __MPLAB_DEBUGGER_SIMULATOR if (string == NULL) { return; } // Track the current line number we're in on the OLED. Valid values are [0, OLED_NUM_LINES). int line = 0; // Track the current character we're writing to the OLED. Valid values are // [0, OLED_CHARS_PER_LINE). int column = 0; // Run through all characters. The maximum length can be the number of lines times the number // of characters per line + three newlines. int i; for (i = 0; string[i] != '\0' && i < (OLED_NUM_LINES * OLED_CHARS_PER_LINE + 3); ++i) { // Move the cursor to the next line if a newline character is encountered. This allows for // early line ending. if (string[i] == '\n') { ++line; column = 0; continue; } else { // Reset to the start of the next line if we've hit the character limit of this line // without seeing a newline. if (column == OLED_CHARS_PER_LINE) { ++line; column = 0; } // Now if we're < OLED_NUM_LINES and < OLED_CHARS_PER_LINE we can proceed. The second // check is implicitly handled by the above if-statement that forces a newline after // encountering a full line of characters. if (line == OLED_NUM_LINES) { break; } // Finally at this point, we can write characters to the OLED. OledDrawChar(column * ASCII_FONT_WIDTH, line * ASCII_FONT_HEIGHT, string[i]); ++column; } } #else printf("%s",string); #endif } void OledClear(OledColor p) { int i; for (i = 0; i < OLED_DRIVER_BUFFER_SIZE; i++) { if (p == OLED_COLOR_WHITE) { rgbOledBmp[i] = 0xFF; } else { rgbOledBmp[i] = 0; } } } void OledSetDisplayInverted(void) { #ifndef __MPLAB_DEBUGGER_SIMULATOR OledDriverSetDisplayInverted(); #endif } void OledSetDisplayNormal(void) { #ifndef __MPLAB_DEBUGGER_SIMULATOR OledDriverSetDisplayNormal(); #endif } void OledOn(void) { #ifndef __MPLAB_DEBUGGER_SIMULATOR OledDriverInitDisplay(); #endif } void OledOff(void) { #ifndef __MPLAB_DEBUGGER_SIMULATOR OledDriverDisableDisplay(); #endif } void OledUpdate(void) { #ifndef __MPLAB_DEBUGGER_SIMULATOR OledDriverUpdateDisplay(); #endif }

OledDriver.c

#include <stdint.h> //CMPE13 Support Library #include "BOARD.h" #include <xc.h> #include <plib.h> #include "OledDriver.h" #define SPI_CHANNEL SPI_CHANNEL2 /** * Constants for the various command values that can be sent to the OLED driver. */ typedef enum { OLED_COMMAND_SET_DISPLAY_LOWER_COLUMN_0 = 0x00, OLED_COMMAND_SET_DISPLAY_UPPER_COLUMN_0 = 0x10, OLED_COMMAND_SET_PAGE = 0x22, OLED_COMMAND_SET_CHARGE_PUMP = 0x8D, OLED_COMMAND_SET_SEGMENT_REMAP = 0xA1, OLED_COMMAND_DISPLAY_NORMAL = 0xA6, OLED_COMMAND_DISPLAY_INVERTED = 0xA7, OLED_COMMAND_DISPLAY_OFF = 0xAE, OLED_COMMAND_DISPLAY_ON = 0xAF, OLED_COMMAND_SET_PRECHARGE_PERIOD = 0xD9, OLED_COMMAND_SET_COM_PINS_CONFIG = 0xDA } OledCommand; /** * Store constants for all settings used with the OLED driver. */ typedef enum { OLED_SETTING_ENABLE_CHARGE_PUMP = 0x14, OLED_SETTING_MAXIMUM_PRECHARGE = 0xF1, OLED_SETTING_SEQUENTIAL_COM_NON_INTERLEAVED = 0x20, OLED_SETTING_REVERSE_ROW_ORDERING = 0xC8 } OledSetting; #define OLED_DRIVER_PAGES 4 /** * This array is the off-screen frame buffer used for rendering. * It isn't possible to read back from the OLED display device, * so display data is rendered into this off-screen buffer and then * copied to the display. * @note Any time this is updated, An `OledDriverUpdateDisplay()` call must be performed. */ uint8_t rgbOledBmp[OLED_DRIVER_BUFFER_SIZE]; // Function prototypes for internal-use functions. void _OledPutBuffer(int size, uint8_t *buffer); uint8_t _Spi2Put(uint8_t bVal); void _DelayMs(unsigned int msec); /** * Initialize the PIC32MX to communicate with the UG-23832HSWEG04 OLED display through the SSD1306 * display controller. */ void OledHostInit(void) { // Open SPI2 as a master in 1-byte mode running at 10MHz. // The peripheral bus is running at 10Mhz, and we want a 10MHz SPI bus clock. int pbClkDiv = 20000000 / 10000000; SpiChnOpen(SPI_CHANNEL2, SPI_OPEN_MSTEN | SPI_OPEN_CKP_HIGH | SPI_OPEN_MODE8, pbClkDiv); // Set RF4-6 as digital outputs for controlling data/command selection, logic power, and display // power. They're all initialized high beforehand, because that disables power. PORTSetBits(IOPORT_F, OLED_DRIVER_CNTLR_POWER_BIT | OLED_DRIVER_OLED_POWER_BIT | OLED_DRIVER_MODE_BIT); PORTSetPinsDigitalOut(OLED_DRIVER_MODE_PORT, OLED_DRIVER_MODE_BIT); // RF4 sets whether the next SPI byte is a data or command byte. PORTSetPinsDigitalOut(OLED_DRIVER_CNTLR_POWER_PORT, OLED_DRIVER_CNTLR_POWER_BIT); // RF5 controls power to the SSD1306 display controller. PORTSetPinsDigitalOut(OLED_DRIVER_OLED_POWER_PORT, OLED_DRIVER_OLED_POWER_BIT); // RF6 controls power to the UG-23832HSWEG04 OLED display. // Set RG9 as a digital output, tied to the reset pin on the SG1306 controller, low => reset. PORTSetBits(OLED_DRIVER_RESET_PORT, OLED_DRIVER_RESET_BIT); PORTSetPinsDigitalOut(OLED_DRIVER_RESET_PORT, OLED_DRIVER_RESET_BIT); } /** * Initialize the OLED display and driver circuitry. */ void OledDriverInitDisplay(void) { // Set the OLED into command mode. PORTClearBits(OLED_DRIVER_MODE_PORT, OLED_DRIVER_MODE_BIT); // Power on the display logic, waiting 1ms for it to start up. PORTClearBits(OLED_DRIVER_CNTLR_POWER_PORT, OLED_DRIVER_CNTLR_POWER_BIT); _DelayMs(1); // Turn off the display. _Spi2Put(OLED_COMMAND_DISPLAY_OFF); // Toggle the reset pin. PORTClearBits(OLED_DRIVER_RESET_PORT, OLED_DRIVER_RESET_BIT); _DelayMs(1); PORTSetBits(OLED_DRIVER_RESET_PORT, OLED_DRIVER_RESET_BIT); // Enable the charge pump and _Spi2Put(OLED_COMMAND_SET_CHARGE_PUMP); _Spi2Put(OLED_SETTING_ENABLE_CHARGE_PUMP); _Spi2Put(OLED_COMMAND_SET_PRECHARGE_PERIOD); _Spi2Put(OLED_SETTING_MAXIMUM_PRECHARGE); // Power on the display, giving it 100ms to start up. PORTClearBits(OLED_DRIVER_OLED_POWER_PORT, OLED_DRIVER_OLED_POWER_BIT); _DelayMs(100); // Invert row numbering so that (0,0) is upper-right. _Spi2Put(OLED_COMMAND_SET_SEGMENT_REMAP); _Spi2Put(OLED_SETTING_REVERSE_ROW_ORDERING); // Set sequential COM configuration with non-interleaved memory. _Spi2Put(OLED_COMMAND_SET_COM_PINS_CONFIG); _Spi2Put(OLED_SETTING_SEQUENTIAL_COM_NON_INTERLEAVED); // And turn on the display. _Spi2Put(OLED_COMMAND_DISPLAY_ON); } /** * Set the LCD to display pixel values as the opposite of how they are actually stored in NVRAM. So * pixels set to black (0) will display as white, and pixels set to white (1) will display as black. */ void OledDriverSetDisplayInverted(void) { // Set the OLED into command mode. PORTClearBits(OLED_DRIVER_MODE_PORT, OLED_DRIVER_MODE_BIT); _Spi2Put(OLED_COMMAND_DISPLAY_INVERTED); } /** * Set the LCD to display pixel values normally, where a 1 indicates white and a 0 indicates black. * This is the default operating mode of the LCD and the mode it starts up in. */ void OledDriverSetDisplayNormal(void) { // Set the OLED into command mode. PORTClearBits(OLED_DRIVER_MODE_PORT, OLED_DRIVER_MODE_BIT); _Spi2Put(OLED_COMMAND_DISPLAY_NORMAL); } /** * Disable the Oled display before power-off. This means powering it up, sending the display off * command, and finally disabling Vbat. */ void OledDriverDisableDisplay(void) { // Set the OLED into command mode. PORTClearBits(OLED_DRIVER_MODE_PORT, OLED_DRIVER_MODE_BIT); // Power on the OLED display logic, waiting for 1ms for it to start up. PORTClearBits(OLED_DRIVER_CNTLR_POWER_PORT, OLED_DRIVER_CNTLR_POWER_BIT); _DelayMs(1); // Send the display off command. _Spi2Put(OLED_COMMAND_DISPLAY_OFF); // And finally power off the display, giving it 100ms to do so. PORTSetBits(OLED_DRIVER_OLED_POWER_PORT, OLED_DRIVER_OLED_POWER_BIT); _DelayMs(100); } /** * Update the display with the contents of rgb0ledBmp. */ void OledDriverUpdateDisplay(void) { uint8_t *pb = rgbOledBmp; int page; for (page = 0; page < OLED_DRIVER_PAGES; page++) { // Set the LCD into command mode. PORTClearBits(OLED_DRIVER_MODE_PORT, OLED_DRIVER_MODE_BIT); // Set the desired page. _Spi2Put(OLED_COMMAND_SET_PAGE); _Spi2Put(page); // Set the starting column back to the origin. _Spi2Put(OLED_COMMAND_SET_DISPLAY_LOWER_COLUMN_0); _Spi2Put(OLED_COMMAND_SET_DISPLAY_UPPER_COLUMN_0); // Return the LCD to data mode. PORTSetBits(OLED_DRIVER_MODE_PORT, OLED_DRIVER_MODE_BIT); // Finally write this entire column to the OLED. // SpiChnPutS() _OledPutBuffer(OLED_DRIVER_PIXEL_COLUMNS, pb); pb += OLED_DRIVER_PIXEL_COLUMNS; } } /** * Write an entire array of uint8_ts over SPI2. * @param size The number of uint8_ts to write. * @param buffer The start of the uint8_t array to write. */ void _OledPutBuffer(int size, uint8_t *buffer) { uint8_t bTmp = 0; int i = bTmp;//non ideal way of forcing Wall error to go away for (i = 0; i < size; ++i) { // Make sure the transmitter is ready while (SPI2STATbits.SPITBE == 0); // Then transmit the desired uint8_t. SPI2BUF = *buffer++; // And wait for a response. It's ignored, but we read it out of the buffer anyways to keep // the buffer clear. while (SPI2STATbits.SPIRBF == 0); bTmp = SPI2BUF; } } /** * Performs a blocking write of a single uint8_t over SPI2. The response uint8_t is returned. * @param bVal The uint8_t to write over SPI. * @return The response to the transmission. */ uint8_t _Spi2Put(uint8_t bVal) { // Make sure the transmitter is ready while (SPI2STATbits.SPITBE == 0); // Then transmit the desired uint8_t. SPI2BUF = bVal; // And wait for a response. while (SPI2STATbits.SPIRBF == 0); // Before returning it. uint8_t bRx = SPI2BUF; return bRx; } /** * Block the processor for the desired number of milliseconds. * @note Assumes processor frequency of 80Mhz. * @param msec The number of milliseconds to block for. */ void _DelayMs(uint32_t msec) { uint32_t tWait, tStart; // Calculate the amount of wait time in terms of core processor frequency. tWait = (80000000L / 2000) * msec; tStart = ReadCoreTimer(); while ((ReadCoreTimer() - tStart) < tWait); // wait for the time to pass }