1.1 --- a/examples/vga-dual/main.c Wed Oct 24 15:56:57 2018 +0200
1.2 +++ b/examples/vga-dual/main.c Wed Oct 24 18:11:22 2018 +0200
1.3 @@ -33,12 +33,6 @@
1.4
1.5
1.6
1.7 -/* Pixel data. */
1.8 -
1.9 -static const uint8_t zerodata[ZERO_LENGTH] = {0};
1.10 -
1.11 -
1.12 -
1.13 /* Blink an attached LED with delays implemented using a loop. */
1.14
1.15 static void blink(uint32_t delay, uint32_t port, uint32_t pins)
1.16 @@ -67,10 +61,6 @@
1.17
1.18 void main(void)
1.19 {
1.20 - init_vga(&display_config, start_visible, update_visible, stop_visible);
1.21 -
1.22 - test_linedata(&display_config);
1.23 -
1.24 init_memory();
1.25 init_pins();
1.26 init_outputs();
1.27 @@ -81,50 +71,19 @@
1.28 lock_config();
1.29
1.30 init_dma();
1.31 -
1.32 - /* Initiate DMA on the Timer2 interrupt transferring line data to the first
1.33 - byte of PORTB. Do not enable the channels for initiation until the visible
1.34 - region is about to start.
1.35 -
1.36 - Here, two DMA channels are interleaved. This appears to provide a more
1.37 - stable picture. */
1.38 -
1.39 - dma_init(0, 3);
1.40 - dma_set_auto_enable(0, 1);
1.41 - dma_set_interrupt(0, T2, 1);
1.42 - dma_set_transfer(0, PHYSICAL((uint32_t) display_config.screen_start),
1.43 - display_config.line_length / 2,
1.44 - HW_PHYSICAL(PORTB), 1,
1.45 - TRANSFER_CELL_SIZE);
1.46 + init_vga(&display_config, 2, -1);
1.47
1.48 - dma_init(1, 3);
1.49 - dma_set_auto_enable(1, 1);
1.50 - dma_set_interrupt(1, T2, 1);
1.51 - dma_set_transfer(1, PHYSICAL((uint32_t) display_config.screen_start +
1.52 - display_config.line_length / 2),
1.53 - display_config.line_length / 2,
1.54 - HW_PHYSICAL(PORTB), 1,
1.55 - TRANSFER_CELL_SIZE);
1.56 -
1.57 - /* Enable DMA on the preceding channel's completion, with the timer event
1.58 - initiating the transfer. */
1.59 + /* Configure VGA output transfer details along with a timer and output
1.60 + compare units for horizontal and vertical sync. */
1.61
1.62 - dma_init(2, 3);
1.63 - dma_set_chaining(2, dma_chain_previous);
1.64 - dma_set_interrupt(2, T2, 1);
1.65 - dma_set_transfer(2, PHYSICAL((uint32_t) zerodata), ZERO_LENGTH,
1.66 - HW_PHYSICAL(PORTB), 1,
1.67 - ZERO_LENGTH);
1.68 - dma_set_receive_events(2, 1);
1.69 -
1.70 - /* Configure a timer and output compare units for horizontal and vertical
1.71 - sync. */
1.72 -
1.73 + vga_configure_transfer(T2, PORTB);
1.74 vga_configure_sync(1, 2, 2);
1.75
1.76 uart_init(1, FPB, 115200);
1.77 uart_on(1);
1.78
1.79 + test_linedata(&display_config);
1.80 +
1.81 interrupts_on();
1.82
1.83 blink(3 << 24, PORTA, 1 << 3);
1.84 @@ -156,40 +115,6 @@
1.85
1.86
1.87
1.88 -/* Enable the channels for the next line. */
1.89 -
1.90 -void start_visible(vga_display_t *vga_display)
1.91 -{
1.92 - dma_set_source(0, PHYSICAL((uint32_t) vga_display->linedata),
1.93 - display_config.line_length / 2);
1.94 - dma_set_source(1, PHYSICAL((uint32_t) vga_display->linedata +
1.95 - display_config.line_length / 2),
1.96 - display_config.line_length / 2);
1.97 - dma_on(0);
1.98 - dma_on(1);
1.99 -}
1.100 -
1.101 -/* Update the channels for the next line. */
1.102 -
1.103 -void update_visible(vga_display_t *vga_display)
1.104 -{
1.105 - dma_set_source(0, PHYSICAL((uint32_t) vga_display->linedata),
1.106 - display_config.line_length / 2);
1.107 - dma_set_source(1, PHYSICAL((uint32_t) vga_display->linedata +
1.108 - display_config.line_length / 2),
1.109 - display_config.line_length / 2);
1.110 -}
1.111 -
1.112 -/* Disable the channels for the next line. */
1.113 -
1.114 -void stop_visible(vga_display_t *vga_display)
1.115 -{
1.116 - dma_off(0);
1.117 - dma_off(1);
1.118 -}
1.119 -
1.120 -
1.121 -
1.122 /* Peripheral pin configuration. */
1.123
1.124 void config_oc(void)
2.1 --- a/examples/vga-dual/main.h Wed Oct 24 15:56:57 2018 +0200
2.2 +++ b/examples/vga-dual/main.h Wed Oct 24 18:11:22 2018 +0200
2.3 @@ -27,10 +27,4 @@
2.4 void config_oc(void);
2.5 void config_uart(void);
2.6
2.7 -/* Display operations. */
2.8 -
2.9 -void start_visible(vga_display_t *vga_display);
2.10 -void update_visible(vga_display_t *vga_display);
2.11 -void stop_visible(vga_display_t *vga_display);
2.12 -
2.13 #endif /* __MAIN_H__ */
3.1 --- a/examples/vga-dual/vga.h Wed Oct 24 15:56:57 2018 +0200
3.2 +++ b/examples/vga-dual/vga.h Wed Oct 24 18:11:22 2018 +0200
3.3 @@ -24,8 +24,6 @@
3.4 #define LINE_COUNT 256 /* distinct display lines */
3.5 #define LINE_MULTIPLIER 2
3.6
3.7 -#define ZERO_LENGTH 1 /* pixels */
3.8 -
3.9 /* 24MHz cycle measurements. */
3.10
3.11 #define HFREQ_LIMIT 643
4.1 --- a/examples/vga-pmp/main.c Wed Oct 24 15:56:57 2018 +0200
4.2 +++ b/examples/vga-pmp/main.c Wed Oct 24 18:11:22 2018 +0200
4.3 @@ -33,12 +33,6 @@
4.4
4.5
4.6
4.7 -/* Pixel data. */
4.8 -
4.9 -static const uint8_t zerodata[ZERO_LENGTH] = {0};
4.10 -
4.11 -
4.12 -
4.13 /* Blink an attached LED with delays implemented using a loop. */
4.14
4.15 static void blink(uint32_t delay, uint32_t port, uint32_t pins)
4.16 @@ -67,10 +61,6 @@
4.17
4.18 void main(void)
4.19 {
4.20 - init_vga(&display_config, start_visible, update_visible, stop_visible);
4.21 -
4.22 - test_linedata(&display_config);
4.23 -
4.24 init_memory();
4.25 init_pins();
4.26 init_outputs();
4.27 @@ -82,6 +72,7 @@
4.28
4.29 init_dma();
4.30 init_pm();
4.31 + init_vga(&display_config, 1, -1);
4.32
4.33 /* Configure parallel master mode. */
4.34
4.35 @@ -89,39 +80,17 @@
4.36 pm_set_output(0, 1, 0);
4.37 pm_on(0);
4.38
4.39 - /* Initiate DMA on the Timer2 interrupt transferring line data to the first
4.40 - byte of PMDIN. Do not enable the channel for initiation until the visible
4.41 - region is about to start. */
4.42 -
4.43 - dma_init(0, 3);
4.44 - dma_set_auto_enable(0, 1);
4.45 - dma_set_interrupt(0, T2, 1);
4.46 - dma_set_transfer(0, PHYSICAL((uint32_t) display_config.screen_start),
4.47 - display_config.line_length,
4.48 - HW_PHYSICAL(PM_REG(0, PMxDIN)), 1,
4.49 - TRANSFER_CELL_SIZE);
4.50 + /* Configure VGA output transfer details along with a timer and output
4.51 + compare units for horizontal and vertical sync. */
4.52
4.53 - /* Enable DMA on the preceding channel's completion, with the timer event
4.54 - initiating the transfer. This "reset" or "zero" transfer is employed to
4.55 - set the pixel level to black in a connected flip-flop. Without the
4.56 - flip-flop it is superfluous. */
4.57 -
4.58 - dma_init(1, 3);
4.59 - dma_set_chaining(1, dma_chain_previous);
4.60 - dma_set_interrupt(1, T2, 1);
4.61 - dma_set_transfer(1, PHYSICAL((uint32_t) zerodata), ZERO_LENGTH,
4.62 - HW_PHYSICAL(PM_REG(0, PMxDIN)), 1,
4.63 - ZERO_LENGTH);
4.64 - dma_set_receive_events(1, 1);
4.65 -
4.66 - /* Configure a timer and output compare units for horizontal and vertical
4.67 - sync. */
4.68 -
4.69 + vga_configure_transfer(T2, PM_REG(0, PMxDIN));
4.70 vga_configure_sync(1, 2, 2);
4.71
4.72 uart_init(1, FPB, 115200);
4.73 uart_on(1);
4.74
4.75 + test_linedata(&display_config);
4.76 +
4.77 interrupts_on();
4.78
4.79 blink(3 << 24, PORTA, 1 << 2);
4.80 @@ -153,32 +122,6 @@
4.81
4.82
4.83
4.84 -/* Enable the channel for the next line. */
4.85 -
4.86 -void start_visible(vga_display_t *vga_display)
4.87 -{
4.88 - dma_set_source(0, PHYSICAL((uint32_t) vga_display->linedata),
4.89 - display_config.line_length);
4.90 - dma_on(0);
4.91 -}
4.92 -
4.93 -/* Update the channel for the next line. */
4.94 -
4.95 -void update_visible(vga_display_t *vga_display)
4.96 -{
4.97 - dma_set_source(0, PHYSICAL((uint32_t) vga_display->linedata),
4.98 - display_config.line_length);
4.99 -}
4.100 -
4.101 -/* Disable the channel for the next line. */
4.102 -
4.103 -void stop_visible(vga_display_t *vga_display)
4.104 -{
4.105 - dma_off(0);
4.106 -}
4.107 -
4.108 -
4.109 -
4.110 /* Peripheral pin configuration. */
4.111
4.112 void config_oc(void)
5.1 --- a/examples/vga-pmp/main.h Wed Oct 24 15:56:57 2018 +0200
5.2 +++ b/examples/vga-pmp/main.h Wed Oct 24 18:11:22 2018 +0200
5.3 @@ -27,10 +27,4 @@
5.4 void config_oc(void);
5.5 void config_uart(void);
5.6
5.7 -/* Display operations. */
5.8 -
5.9 -void start_visible(vga_display_t *vga_display);
5.10 -void update_visible(vga_display_t *vga_display);
5.11 -void stop_visible(vga_display_t *vga_display);
5.12 -
5.13 #endif /* __MAIN_H__ */
6.1 --- a/examples/vga-pmp/vga.h Wed Oct 24 15:56:57 2018 +0200
6.2 +++ b/examples/vga-pmp/vga.h Wed Oct 24 18:11:22 2018 +0200
6.3 @@ -24,8 +24,6 @@
6.4 #define LINE_COUNT 256 /* distinct display lines */
6.5 #define LINE_MULTIPLIER 2
6.6
6.7 -#define ZERO_LENGTH 1 /* pixels */
6.8 -
6.9 /* 48MHz cycle measurements. */
6.10
6.11 #define HFREQ_LIMIT 1286
7.1 --- a/examples/vga-timer/main.c Wed Oct 24 15:56:57 2018 +0200
7.2 +++ b/examples/vga-timer/main.c Wed Oct 24 18:11:22 2018 +0200
7.3 @@ -33,12 +33,6 @@
7.4
7.5
7.6
7.7 -/* Pixel data. */
7.8 -
7.9 -static const uint8_t zerodata[ZERO_LENGTH] = {0};
7.10 -
7.11 -
7.12 -
7.13 /* Blink an attached LED with delays implemented using a loop. */
7.14
7.15 static void blink(uint32_t delay, uint32_t port, uint32_t pins)
7.16 @@ -67,10 +61,6 @@
7.17
7.18 void main(void)
7.19 {
7.20 - init_vga(&display_config, start_visible, update_visible, stop_visible);
7.21 -
7.22 - test_linedata(&display_config);
7.23 -
7.24 init_memory();
7.25 init_pins();
7.26 init_outputs();
7.27 @@ -81,6 +71,7 @@
7.28 lock_config();
7.29
7.30 init_dma();
7.31 + init_vga(&display_config, 2, T2);
7.32
7.33 /* Peripheral relationships:
7.34
7.35 @@ -94,64 +85,22 @@
7.36 Timer3 -> DMA3: zerodata -> PORTB
7.37 */
7.38
7.39 - /* Initiate DMA on the Timer2 interrupt condition, transferring line data to
7.40 - the first byte of PORTB. Do not enable the channel for initiation until
7.41 - the visible region is about to start. */
7.42 -
7.43 - dma_init(1, 3);
7.44 - dma_set_auto_enable(1, 1);
7.45 - dma_set_interrupt(1, T2, 1);
7.46 - dma_set_transfer(1, PHYSICAL((uint32_t) zerodata), ZERO_LENGTH,
7.47 - HW_PHYSICAL(PORTB), 1,
7.48 - ZERO_LENGTH);
7.49 -
7.50 - /* Enable DMA on the zero channel's completion, with the Timer3
7.51 - interrupt condition initiating transfers. */
7.52 -
7.53 - dma_init(0, 2);
7.54 - dma_set_chaining(0, dma_chain_next);
7.55 - dma_set_interrupt(0, T3, 1);
7.56 - dma_set_transfer(0, PHYSICAL((uint32_t) display_config.screen_start),
7.57 - display_config.line_length / 2,
7.58 - HW_PHYSICAL(PORTB), 1,
7.59 - TRANSFER_CELL_SIZE);
7.60 + /* Configure VGA output transfer details along with a timer and output
7.61 + compare units for horizontal and vertical sync. */
7.62
7.63 - /* Enable DMA on the zero channel's completion, with the Timer3
7.64 - interrupt condition initiating transfers. */
7.65 -
7.66 - dma_init(2, 2);
7.67 - dma_set_chaining(2, dma_chain_previous);
7.68 - dma_set_interrupt(2, T3, 1);
7.69 - dma_set_transfer(2, PHYSICAL((uint32_t) display_config.screen_start +
7.70 - display_config.line_length / 2),
7.71 - display_config.line_length / 2,
7.72 - HW_PHYSICAL(PORTB), 1,
7.73 - TRANSFER_CELL_SIZE);
7.74 -
7.75 - /* Enable DMA on the preceding channel's completion, with Timer3 initiating
7.76 - transfers. */
7.77 -
7.78 - dma_init(3, 3);
7.79 - dma_set_chaining(3, dma_chain_previous);
7.80 - dma_set_interrupt(3, T3, 1);
7.81 - dma_set_transfer(3, PHYSICAL((uint32_t) zerodata), ZERO_LENGTH,
7.82 - HW_PHYSICAL(PORTB), 1,
7.83 - ZERO_LENGTH);
7.84 - dma_set_receive_events(3, 1);
7.85 + vga_configure_transfer(T3, PORTB);
7.86 + vga_configure_sync(1, 2, 2);
7.87
7.88 /* Configure a timer for line data transfers. */
7.89
7.90 timer_init(3, 0, 1);
7.91 timer_on(3);
7.92
7.93 - /* Configure a timer and output compare units for horizontal and vertical
7.94 - sync. */
7.95 -
7.96 - vga_configure_sync(1, 2, 2);
7.97 -
7.98 uart_init(1, FPB, 115200);
7.99 uart_on(1);
7.100
7.101 + test_linedata(&display_config);
7.102 +
7.103 interrupts_on();
7.104
7.105 blink(3 << 24, PORTA, 1 << 3);
7.106 @@ -183,38 +132,6 @@
7.107
7.108
7.109
7.110 -/* Enable the channels for the next line. */
7.111 -
7.112 -void start_visible(vga_display_t *vga_display)
7.113 -{
7.114 - dma_set_source(0, PHYSICAL((uint32_t) vga_display->linedata),
7.115 - display_config.line_length / 2);
7.116 - dma_set_source(2, PHYSICAL((uint32_t) vga_display->linedata +
7.117 - display_config.line_length / 2),
7.118 - display_config.line_length / 2);
7.119 - dma_on(1);
7.120 -}
7.121 -
7.122 -/* Update the channels for the next line. */
7.123 -
7.124 -void update_visible(vga_display_t *vga_display)
7.125 -{
7.126 - dma_set_source(0, PHYSICAL((uint32_t) vga_display->linedata),
7.127 - display_config.line_length / 2);
7.128 - dma_set_source(2, PHYSICAL((uint32_t) vga_display->linedata +
7.129 - display_config.line_length / 2),
7.130 - display_config.line_length / 2);
7.131 -}
7.132 -
7.133 -/* Disable the channels for the next line. */
7.134 -
7.135 -void stop_visible(vga_display_t *vga_display)
7.136 -{
7.137 - dma_off(1);
7.138 -}
7.139 -
7.140 -
7.141 -
7.142 /* Peripheral pin configuration. */
7.143
7.144 void config_oc(void)
8.1 --- a/examples/vga-timer/main.h Wed Oct 24 15:56:57 2018 +0200
8.2 +++ b/examples/vga-timer/main.h Wed Oct 24 18:11:22 2018 +0200
8.3 @@ -27,10 +27,4 @@
8.4 void config_oc(void);
8.5 void config_uart(void);
8.6
8.7 -/* Display operations. */
8.8 -
8.9 -void start_visible(vga_display_t *vga_display);
8.10 -void update_visible(vga_display_t *vga_display);
8.11 -void stop_visible(vga_display_t *vga_display);
8.12 -
8.13 #endif /* __MAIN_H__ */
9.1 --- a/examples/vga-timer/vga.h Wed Oct 24 15:56:57 2018 +0200
9.2 +++ b/examples/vga-timer/vga.h Wed Oct 24 18:11:22 2018 +0200
9.3 @@ -24,8 +24,6 @@
9.4 #define LINE_COUNT 128 /* distinct display lines */
9.5 #define LINE_MULTIPLIER 4
9.6
9.7 -#define ZERO_LENGTH 1 /* pixels */
9.8 -
9.9 /* 24MHz cycle measurements. */
9.10
9.11 #define HFREQ_LIMIT 643
10.1 --- a/examples/vga/main.c Wed Oct 24 15:56:57 2018 +0200
10.2 +++ b/examples/vga/main.c Wed Oct 24 18:11:22 2018 +0200
10.3 @@ -33,12 +33,6 @@
10.4
10.5
10.6
10.7 -/* Pixel data. */
10.8 -
10.9 -static const uint8_t zerodata[ZERO_LENGTH] = {0};
10.10 -
10.11 -
10.12 -
10.13 /* Blink an attached LED with delays implemented using a loop. */
10.14
10.15 static void blink(uint32_t delay, uint32_t port, uint32_t pins)
10.16 @@ -67,10 +61,6 @@
10.17
10.18 void main(void)
10.19 {
10.20 - init_vga(&display_config, start_visible, update_visible, stop_visible);
10.21 -
10.22 - test_linedata(&display_config);
10.23 -
10.24 init_memory();
10.25 init_pins();
10.26 init_outputs();
10.27 @@ -81,38 +71,19 @@
10.28 lock_config();
10.29
10.30 init_dma();
10.31 -
10.32 - /* Initiate DMA on the Timer2 interrupt transferring line data to the first
10.33 - byte of PORTB. Do not enable the channel for initiation until the visible
10.34 - region is about to start. */
10.35 -
10.36 - dma_init(0, 3);
10.37 - dma_set_auto_enable(0, 1);
10.38 - dma_set_interrupt(0, T2, 1);
10.39 - dma_set_transfer(0, PHYSICAL((uint32_t) display_config.screen_start),
10.40 - display_config.line_length,
10.41 - HW_PHYSICAL(PORTB), 1,
10.42 - TRANSFER_CELL_SIZE);
10.43 + init_vga(&display_config, 1, -1);
10.44
10.45 - /* Enable DMA on the preceding channel's completion, with the timer event
10.46 - initiating the transfer. */
10.47 + /* Configure VGA output transfer details along with a timer and output
10.48 + compare units for horizontal and vertical sync. */
10.49
10.50 - dma_init(1, 3);
10.51 - dma_set_chaining(1, dma_chain_previous);
10.52 - dma_set_interrupt(1, T2, 1);
10.53 - dma_set_transfer(1, PHYSICAL((uint32_t) zerodata), ZERO_LENGTH,
10.54 - HW_PHYSICAL(PORTB), 1,
10.55 - ZERO_LENGTH);
10.56 - dma_set_receive_events(1, 1);
10.57 -
10.58 - /* Configure a timer and output compare units for horizontal and vertical
10.59 - sync. */
10.60 -
10.61 + vga_configure_transfer(T2, PORTB);
10.62 vga_configure_sync(1, 2, 2);
10.63
10.64 uart_init(1, FPB, 115200);
10.65 uart_on(1);
10.66
10.67 + test_linedata(&display_config);
10.68 +
10.69 interrupts_on();
10.70
10.71 blink(3 << 24, PORTA, 1 << 3);
10.72 @@ -144,32 +115,6 @@
10.73
10.74
10.75
10.76 -/* Enable the channel for the next line. */
10.77 -
10.78 -void start_visible(vga_display_t *vga_display)
10.79 -{
10.80 - dma_set_source(0, PHYSICAL((uint32_t) vga_display->linedata),
10.81 - display_config.line_length);
10.82 - dma_on(0);
10.83 -}
10.84 -
10.85 -/* Update the channel for the next line. */
10.86 -
10.87 -void update_visible(vga_display_t *vga_display)
10.88 -{
10.89 - dma_set_source(0, PHYSICAL((uint32_t) vga_display->linedata),
10.90 - display_config.line_length);
10.91 -}
10.92 -
10.93 -/* Disable the channel for the next line. */
10.94 -
10.95 -void stop_visible(vga_display_t *vga_display)
10.96 -{
10.97 - dma_off(0);
10.98 -}
10.99 -
10.100 -
10.101 -
10.102 /* Peripheral pin configuration. */
10.103
10.104 void config_oc(void)
11.1 --- a/examples/vga/main.h Wed Oct 24 15:56:57 2018 +0200
11.2 +++ b/examples/vga/main.h Wed Oct 24 18:11:22 2018 +0200
11.3 @@ -27,10 +27,4 @@
11.4 void config_oc(void);
11.5 void config_uart(void);
11.6
11.7 -/* Display operations. */
11.8 -
11.9 -void start_visible(vga_display_t *vga_display);
11.10 -void update_visible(vga_display_t *vga_display);
11.11 -void stop_visible(vga_display_t *vga_display);
11.12 -
11.13 #endif /* __MAIN_H__ */
12.1 --- a/examples/vga/vga.h Wed Oct 24 15:56:57 2018 +0200
12.2 +++ b/examples/vga/vga.h Wed Oct 24 18:11:22 2018 +0200
12.3 @@ -24,8 +24,6 @@
12.4 #define LINE_COUNT 256 /* distinct display lines */
12.5 #define LINE_MULTIPLIER 2
12.6
12.7 -#define ZERO_LENGTH 1 /* pixels */
12.8 -
12.9 /* 24MHz cycle measurements. */
12.10
12.11 #define HFREQ_LIMIT 643
13.1 --- a/include/display.h Wed Oct 24 15:56:57 2018 +0200
13.2 +++ b/include/display.h Wed Oct 24 18:11:22 2018 +0200
13.3 @@ -44,7 +44,11 @@
13.4
13.5 /* Number of consecutive pixels provided by a framebuffer region. */
13.6
13.7 - int cell_size;
13.8 + uint32_t cell_size;
13.9 +
13.10 + /* DMA transfer sizes. */
13.11 +
13.12 + uint32_t transfer_cell_size;
13.13
13.14 /* Display line positions. */
13.15
14.1 --- a/include/display_config.h Wed Oct 24 15:56:57 2018 +0200
14.2 +++ b/include/display_config.h Wed Oct 24 18:11:22 2018 +0200
14.3 @@ -40,6 +40,7 @@
14.4 .line_count = LINE_COUNT,
14.5 .line_multiplier = LINE_MULTIPLIER,
14.6 .cell_size = CELL_SIZE,
14.7 + .transfer_cell_size = TRANSFER_CELL_SIZE,
14.8
14.9 /* Define display region properties. */
14.10
15.1 --- a/include/init.h Wed Oct 24 15:56:57 2018 +0200
15.2 +++ b/include/init.h Wed Oct 24 18:11:22 2018 +0200
15.3 @@ -70,13 +70,14 @@
15.4
15.5 void dma_set_receive_events(int channel, int enable);
15.6
15.7 -void dma_set_source(int channel,
15.8 - uint32_t source_start_address, uint16_t source_size);
15.9 +void dma_set_cell(int channel, uint32_t size);
15.10 +void dma_set_destination(int channel, uint32_t start_address, uint32_t size);
15.11 +void dma_set_source(int channel, uint32_t start_address, uint32_t size);
15.12
15.13 void dma_set_transfer(int channel,
15.14 - uint32_t source_start_address, uint16_t source_size,
15.15 - uint32_t destination_start_address, uint16_t destination_size,
15.16 - uint16_t cell_size);
15.17 + uint32_t source_start_address, uint32_t source_size,
15.18 + uint32_t destination_start_address, uint32_t destination_size,
15.19 + uint32_t cell_size);
15.20
15.21 int DMA_INT_FLAGS(int channel, uint8_t flags);
15.22
16.1 --- a/include/vga_display.h Wed Oct 24 15:56:57 2018 +0200
16.2 +++ b/include/vga_display.h Wed Oct 24 18:11:22 2018 +0200
16.3 @@ -20,6 +20,7 @@
16.4 #ifndef __VGA_DISPLAY_H__
16.5 #define __VGA_DISPLAY_H__
16.6
16.7 +#include "pic32_c.h"
16.8 #include "display.h"
16.9
16.10
16.11 @@ -32,11 +33,9 @@
16.12
16.13 void (*state_handler)();
16.14
16.15 - /* Display state handlers. */
16.16 + /* DMA transfer properties. */
16.17
16.18 - void (*start_visible)();
16.19 - void (*update_visible)();
16.20 - void (*stop_visible)();
16.21 + int line_channels, initiating_int_num;
16.22
16.23 /* Horizontal and vertical sync peripherals. */
16.24
16.25 @@ -60,13 +59,19 @@
16.26
16.27 /* Initialisation. */
16.28
16.29 -void init_vga(display_config_t *display_config,
16.30 - void (*start_visible)(),
16.31 - void (*update_visible)(),
16.32 - void (*stop_visible)());
16.33 +void init_vga(display_config_t *display_config, int line_channels,
16.34 + int initiating_int_num);
16.35
16.36 void vga_configure_sync(int hsync_unit, int vsync_unit, int timer);
16.37
16.38 +void vga_configure_transfer(int transfer_int_num, uint32_t output);
16.39 +
16.40 +void vga_configure_line_channel(int channel, int int_num, enum dma_chain chain,
16.41 + uint32_t output);
16.42 +
16.43 +void vga_configure_zero_channel(int channel, int int_num, int initiating,
16.44 + uint32_t output);
16.45 +
16.46 /* Interrupt handlers. */
16.47
16.48 void vga_interrupt_handler(void);
16.49 @@ -78,6 +83,13 @@
16.50 void vfp_active(void);
16.51 void vsync_active(void);
16.52
16.53 +/* Display operations. */
16.54 +
16.55 +void start_visible(void);
16.56 +void update_visible(void);
16.57 +void stop_visible(void);
16.58 +void update_transfers(int enable);
16.59 +
16.60 /* Vertical sync operations. */
16.61
16.62 void vsync_high(void);
17.1 --- a/lib/init.c Wed Oct 24 15:56:57 2018 +0200
17.2 +++ b/lib/init.c Wed Oct 24 18:11:22 2018 +0200
17.3 @@ -190,33 +190,51 @@
17.4 (enable ? SET_REG : CLR_REG)(DMA_REG(channel, DCHxCON), 1 << 6);
17.5 }
17.6
17.7 -/* Set a channel's source. */
17.8 +/* Set a channel's cell size. */
17.9
17.10 -void dma_set_source(int channel,
17.11 - uint32_t source_start_address, uint16_t source_size)
17.12 +void dma_set_cell(int channel, uint32_t size)
17.13 {
17.14 if ((channel < DCHMIN) || (channel > DCHMAX))
17.15 return;
17.16
17.17 - REG(DMA_REG(channel, DCHxSSIZ)) = source_size;
17.18 - REG(DMA_REG(channel, DCHxSSA)) = source_start_address;
17.19 + REG(DMA_REG(channel, DCHxCSIZ)) = size;
17.20 +}
17.21 +
17.22 +/* Set a channel's destination. */
17.23 +
17.24 +void dma_set_destination(int channel, uint32_t start_address, uint32_t size)
17.25 +{
17.26 + if ((channel < DCHMIN) || (channel > DCHMAX))
17.27 + return;
17.28 +
17.29 + REG(DMA_REG(channel, DCHxDSIZ)) = size;
17.30 + REG(DMA_REG(channel, DCHxDSA)) = start_address;
17.31 +}
17.32 +
17.33 +/* Set a channel's source. */
17.34 +
17.35 +void dma_set_source(int channel, uint32_t start_address, uint32_t size)
17.36 +{
17.37 + if ((channel < DCHMIN) || (channel > DCHMAX))
17.38 + return;
17.39 +
17.40 + REG(DMA_REG(channel, DCHxSSIZ)) = size;
17.41 + REG(DMA_REG(channel, DCHxSSA)) = start_address;
17.42 }
17.43
17.44 /* Set a channel's transfer parameters. */
17.45
17.46 void dma_set_transfer(int channel,
17.47 - uint32_t source_start_address, uint16_t source_size,
17.48 - uint32_t destination_start_address, uint16_t destination_size,
17.49 - uint16_t cell_size)
17.50 + uint32_t source_start_address, uint32_t source_size,
17.51 + uint32_t destination_start_address, uint32_t destination_size,
17.52 + uint32_t cell_size)
17.53 {
17.54 if ((channel < DCHMIN) || (channel > DCHMAX))
17.55 return;
17.56
17.57 dma_set_source(channel, source_start_address, source_size);
17.58 -
17.59 - REG(DMA_REG(channel, DCHxDSIZ)) = destination_size;
17.60 - REG(DMA_REG(channel, DCHxDSA)) = destination_start_address;
17.61 - REG(DMA_REG(channel, DCHxCSIZ)) = cell_size;
17.62 + dma_set_destination(channel, destination_start_address, destination_size);
17.63 + dma_set_cell(channel, cell_size);
17.64 }
17.65
17.66 /* Configure interrupts caused by the channel. */
18.1 --- a/lib/vga_display.c Wed Oct 24 15:56:57 2018 +0200
18.2 +++ b/lib/vga_display.c Wed Oct 24 18:11:22 2018 +0200
18.3 @@ -27,24 +27,23 @@
18.4
18.5 vga_display_t vga_display;
18.6
18.7 +/* Pixel data. */
18.8 +
18.9 +static const int ZERO_LENGTH = 1;
18.10 +static const uint8_t zerodata[1] = {0};
18.11 +
18.12
18.13
18.14 /* Initialise the state machine. */
18.15
18.16 -void init_vga(display_config_t *display_config,
18.17 - void (*start_visible)(),
18.18 - void (*update_visible)(),
18.19 - void (*stop_visible)())
18.20 +void init_vga(display_config_t *display_config, int line_channels,
18.21 + int initiating_int_num)
18.22 {
18.23 /* Display parameters. */
18.24
18.25 vga_display.display_config = display_config;
18.26 -
18.27 - /* Display state handlers. */
18.28 -
18.29 - vga_display.start_visible = start_visible;
18.30 - vga_display.update_visible = update_visible;
18.31 - vga_display.stop_visible = stop_visible;
18.32 + vga_display.line_channels = line_channels;
18.33 + vga_display.initiating_int_num = initiating_int_num;
18.34
18.35 /* Initial state. */
18.36
18.37 @@ -52,6 +51,101 @@
18.38 vga_display.line = 0;
18.39 }
18.40
18.41 +
18.42 +
18.43 +/* Configure DMA channels for the transfer of pixel data. */
18.44 +
18.45 +void vga_configure_transfer(int transfer_int_num, uint32_t output)
18.46 +{
18.47 + int initiating_channel = vga_display.initiating_int_num >= 0;
18.48 + int dual_channel = vga_display.line_channels == 2;
18.49 + int channel = 0;
18.50 +
18.51 + /* Where dual line channels are involved, put the first before any
18.52 + initiating channel, chaining it to such a channel. */
18.53 +
18.54 + if (dual_channel)
18.55 + {
18.56 + vga_configure_line_channel(channel++, transfer_int_num,
18.57 + initiating_channel ? dma_chain_next : dma_chain_none,
18.58 + output);
18.59 + }
18.60 +
18.61 + /* Introduce a special initiating channel if an interrupt has been
18.62 + indicated. */
18.63 +
18.64 + if (initiating_channel)
18.65 + {
18.66 + vga_configure_zero_channel(channel++, vga_display.initiating_int_num, 1,
18.67 + output);
18.68 + }
18.69 +
18.70 + /* A line channel is always configured, chaining it to any initiating
18.71 + channel. */
18.72 +
18.73 + vga_configure_line_channel(channel++, transfer_int_num,
18.74 + initiating_channel ? dma_chain_previous : dma_chain_none,
18.75 + output);
18.76 +
18.77 + /* A zero channel is always configured, chaining it to the preceding line
18.78 + channel, with the same transfer interrupt initiating the transfer. */
18.79 +
18.80 + vga_configure_zero_channel(channel, transfer_int_num, 0, output);
18.81 +}
18.82 +
18.83 +void vga_configure_line_channel(int channel, int int_num, enum dma_chain chain,
18.84 + uint32_t output)
18.85 +{
18.86 + dma_init(channel, 2);
18.87 +
18.88 + /* If initiating, configure to always be enabled. */
18.89 +
18.90 + if (chain == dma_chain_none)
18.91 + dma_set_auto_enable(channel, 1);
18.92 +
18.93 + /* Chain to either the previous or next channel where a special initiating
18.94 + channel is used. */
18.95 +
18.96 + else
18.97 + dma_set_chaining(channel, chain);
18.98 +
18.99 + /* Initiate DMA on the transfer interrupt, transferring line data to the
18.100 + first byte of the output word. */
18.101 +
18.102 + dma_set_interrupt(channel, int_num, 1);
18.103 +
18.104 + dma_set_destination(channel, HW_PHYSICAL(output), 1);
18.105 + dma_set_cell(channel, vga_display.display_config->transfer_cell_size);
18.106 +}
18.107 +
18.108 +void vga_configure_zero_channel(int channel, int int_num, int initiating,
18.109 + uint32_t output)
18.110 +{
18.111 + dma_init(channel, 3);
18.112 +
18.113 + /* If initiating, configure to always be enabled. */
18.114 +
18.115 + if (initiating)
18.116 + dma_set_auto_enable(channel, 1);
18.117 +
18.118 + /* Otherwise, chain to the preceding channel and register prior transfer
18.119 + events before the channel is activated. */
18.120 +
18.121 + else
18.122 + {
18.123 + dma_set_chaining(channel, dma_chain_previous);
18.124 + dma_set_receive_events(channel, 1);
18.125 + }
18.126 +
18.127 + /* Transfer upon the indicated interrupt condition. */
18.128 +
18.129 + dma_set_interrupt(channel, int_num, 1);
18.130 + dma_set_transfer(channel, PHYSICAL((uint32_t) zerodata),
18.131 + ZERO_LENGTH,
18.132 + HW_PHYSICAL(output), 1,
18.133 + ZERO_LENGTH);
18.134 +}
18.135 +
18.136 /* Configure a timer and output compare units for horizontal and vertical
18.137 sync. */
18.138
18.139 @@ -117,7 +211,7 @@
18.140 /* Set the line address. */
18.141
18.142 vga_display.linedata = vga_display.display_config->screen_start;
18.143 - vga_display.start_visible(&vga_display);
18.144 + start_visible();
18.145 }
18.146
18.147 /* Visible region. */
18.148 @@ -136,7 +230,7 @@
18.149 vga_display.linedata -= vga_display.display_config->screen_size;
18.150 }
18.151
18.152 - vga_display.update_visible(&vga_display);
18.153 + update_visible();
18.154 return;
18.155 }
18.156
18.157 @@ -146,7 +240,7 @@
18.158
18.159 /* Disable the channel for the next line. */
18.160
18.161 - vga_display.stop_visible(&vga_display);
18.162 + stop_visible();
18.163 }
18.164
18.165 /* Vertical front porch region. */
18.166 @@ -184,6 +278,87 @@
18.167
18.168
18.169
18.170 +/* Enable the channels for the next line. */
18.171 +
18.172 +void start_visible(void)
18.173 +{
18.174 + update_visible();
18.175 + update_transfers(1);
18.176 +}
18.177 +
18.178 +/* Update the channels for the next line. */
18.179 +
18.180 +void update_visible(void)
18.181 +{
18.182 + uint32_t transfer_start = (uint32_t) vga_display.linedata;
18.183 + uint32_t transfer_length = vga_display.display_config->line_length /
18.184 + vga_display.line_channels;
18.185 +
18.186 + /* Determine whether an initiating channel is used. */
18.187 +
18.188 + int initiating_channel = vga_display.initiating_int_num >= 0;
18.189 + int channel = 0;
18.190 +
18.191 + /* Update the source of a secondary line channel. */
18.192 +
18.193 + if (vga_display.line_channels == 2)
18.194 + {
18.195 + dma_set_source(channel, PHYSICAL(transfer_start), transfer_length);
18.196 + transfer_start += transfer_length;
18.197 + channel++;
18.198 + }
18.199 +
18.200 + /* Skip any initiating channel. */
18.201 +
18.202 + if (initiating_channel)
18.203 + channel++;
18.204 +
18.205 + /* Update the source of a line channel, with potentially updated start
18.206 + address. */
18.207 +
18.208 + dma_set_source(channel, PHYSICAL(transfer_start), transfer_length);
18.209 +}
18.210 +
18.211 +/* Disable the channels for the next line. */
18.212 +
18.213 +void stop_visible(void)
18.214 +{
18.215 + update_transfers(0);
18.216 +}
18.217 +
18.218 +/* Enable or disable transfers. */
18.219 +
18.220 +void update_transfers(int enable)
18.221 +{
18.222 + int initiating_channel = vga_display.initiating_int_num >= 0;
18.223 + int channel = 0;
18.224 + void (*fn)() = enable ? dma_on : dma_off;
18.225 +
18.226 + /* Update line channels if no initiating channel is used. */
18.227 +
18.228 + if (vga_display.line_channels == 2)
18.229 + {
18.230 + if (!initiating_channel)
18.231 + fn(channel);
18.232 + channel++;
18.233 + }
18.234 +
18.235 + /* Update any initiating channel. */
18.236 +
18.237 + if (initiating_channel)
18.238 + {
18.239 + fn(channel);
18.240 + channel++;
18.241 + }
18.242 +
18.243 + /* Update line channels if no initiating channel is used. */
18.244 +
18.245 + if (!initiating_channel)
18.246 + fn(channel);
18.247 +}
18.248 +
18.249 +
18.250 +
18.251 /* Bring vsync low (single compare, output driven low) when the next line
18.252 starts. */
18.253