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 /* Blink an attached LED with delays implemented using a loop. */ 37 38 static void blink(uint32_t delay, uint32_t port, uint32_t pins) 39 { 40 uint32_t counter; 41 42 /* Clear outputs (LED). */ 43 44 CLR_REG(port, pins); 45 46 while (1) 47 { 48 counter = delay; 49 50 while (counter--) __asm__(""); /* retain loop */ 51 52 /* Invert outputs (LED). */ 53 54 INV_REG(port, pins); 55 } 56 } 57 58 59 60 /* Main program. */ 61 62 void main(void) 63 { 64 init_memory(); 65 init_pins(); 66 init_outputs(); 67 68 unlock_config(); 69 config_oc(); 70 config_uart(); 71 lock_config(); 72 73 init_dma(); 74 init_pm(); 75 76 /* Configure parallel master mode. */ 77 78 pm_init(0, 0b10); 79 pm_set_output(0, 1, 0); 80 pm_on(0); 81 82 /* Initialise VGA output with a single line channel, configuring Timer2, 83 with no transfer timer and thus no initiating channel. */ 84 85 init_vga_with_timers(&display_config, 1, 2, 0); 86 87 /* Configure VGA output transfer to the parallel mode output register, also 88 configuring output compare units for horizontal and vertical sync. */ 89 90 vga_configure_transfer(PM_REG(0, PMxDIN)); 91 vga_configure_sync(1, 2); 92 93 uart_init(1, FPB, 115200); 94 uart_on(1); 95 96 test_linedata(&display_config); 97 98 interrupts_on(); 99 100 blink(3 << 24, PORTA, 1 << 2); 101 } 102 103 104 105 /* Exception and interrupt handlers. */ 106 107 void exception_handler(void) 108 { 109 blink(3 << 12, PORTA, 1 << 2); 110 } 111 112 void interrupt_handler(void) 113 { 114 uint32_t ifs; 115 116 /* Check for a OC1 interrupt condition. */ 117 118 ifs = REG(OCIFS) & OC_INT_FLAGS(1, OCxIF); 119 120 if (ifs) 121 { 122 vga_interrupt_handler(); 123 CLR_REG(OCIFS, ifs); 124 } 125 } 126 127 128 129 /* Peripheral pin configuration. */ 130 131 void config_oc(void) 132 { 133 /* Map OC1 to RPB4. */ 134 135 REG(RPB4R) = 0b0101; /* RPB4R<3:0> = 0101 (OC1) */ 136 137 /* Map OC2 to RPB5. */ 138 139 REG(RPB5R) = 0b0101; /* RPB5R<3:0> = 0101 (OC2) */ 140 } 141 142 void config_uart(void) 143 { 144 /* Map U1RX to RPB13. */ 145 146 REG(U1RXR) = 0b0011; /* U1RXR<3:0> = 0011 (RPB13) */ 147 148 /* Map U1TX to RPB15. */ 149 150 REG(RPB15R) = 0b0001; /* RPB15R<3:0> = 0001 (U1TX) */ 151 152 /* Set RPB13 to input. */ 153 154 SET_REG(TRISB, 1 << 13); 155 }