CommonPIC32

Annotated examples/vga-timer/main.c

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