1 /* 2 * Generate a VGA signal using a PIC32 microcontroller. 3 * 4 * Copyright (C) 2017, 2018 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 21 #include "pic32_c.h" 22 #include "init.h" 23 #include "debug.h" 24 25 /* Specific functionality. */ 26 27 #include "main.h" 28 #include "devconfig.h" 29 #include "vga.h" 30 #include "display.h" 31 #include "display_config.h" 32 #include "vga_display.h" 33 34 35 36 /* Define timers if not indicated in the build configuration. */ 37 38 #ifndef LINE_CHANNELS 39 #define LINE_CHANNELS 1 40 #endif 41 42 #ifndef LINE_TIMER 43 #define LINE_TIMER 2 44 #endif 45 46 #ifndef TRANSFER_TIMER 47 #define TRANSFER_TIMER 0 48 #endif 49 50 51 52 /* Blink an attached LED with delays implemented using a loop. */ 53 54 static void blink(uint32_t delay, uint32_t port, uint32_t pins) 55 { 56 uint32_t counter; 57 58 /* Clear outputs (LED). */ 59 60 CLR_REG(port, pins); 61 62 while (1) 63 { 64 counter = delay; 65 66 while (counter--) __asm__(""); /* retain loop */ 67 68 /* Invert outputs (LED). */ 69 70 INV_REG(port, pins); 71 } 72 } 73 74 75 76 /* Main program. */ 77 78 void main(void) 79 { 80 init_memory(); 81 init_pins(); 82 init_outputs(); 83 84 unlock_config(); 85 config_oc(); 86 config_uart(); 87 lock_config(); 88 89 init_dma(); 90 91 /* Initialise VGA output with one or two line channels, configuring a line 92 timer and any transfer timer, with an initiating channel being introduced 93 if a transfer timer is specified. */ 94 95 init_vga_with_timers(&display_config, LINE_CHANNELS, LINE_TIMER, TRANSFER_TIMER); 96 97 /* Configure VGA output transfer to the output register, also configuring 98 output compare units for horizontal and vertical sync. */ 99 100 vga_configure_transfer(PORTB); 101 vga_configure_sync(1, 2); 102 103 uart_init(1, FPB, 115200); 104 uart_on(1); 105 106 test_linedata(&display_config); 107 108 interrupts_on(); 109 110 blink(3 << 24, PORTA, 1 << 3); 111 } 112 113 114 115 /* Exception and interrupt handlers. */ 116 117 void exception_handler(void) 118 { 119 blink(3 << 12, PORTA, 1 << 3); 120 } 121 122 void interrupt_handler(void) 123 { 124 uint32_t ifs; 125 126 /* Check for a OC1 interrupt condition. */ 127 128 ifs = REG(OCIFS) & OC_INT_FLAGS(1, OCxIF); 129 130 if (ifs) 131 { 132 vga_interrupt_handler(); 133 CLR_REG(OCIFS, ifs); 134 } 135 } 136 137 138 139 /* Peripheral pin configuration. */ 140 141 void config_oc(void) 142 { 143 /* Map OC1 to RPA0. */ 144 145 REG(RPA0R) = 0b0101; /* RPA0R<3:0> = 0101 (OC1) */ 146 147 /* Map OC2 to RPA1. */ 148 149 REG(RPA1R) = 0b0101; /* RPA1R<3:0> = 0101 (OC2) */ 150 } 151 152 void config_uart(void) 153 { 154 /* Map U1RX to RPB13. */ 155 156 REG(U1RXR) = 0b0011; /* U1RXR<3:0> = 0011 (RPB13) */ 157 158 /* Map U1TX to RPB15. */ 159 160 REG(RPB15R) = 0b0001; /* RPB15R<3:0> = 0001 (U1TX) */ 161 162 /* Set RPB13 to input. */ 163 164 SET_REG(TRISB, 1 << 13); 165 }