Search
Program for working with knobs QtRvSim
#base of SPILED port region .equ SPILED_REG_BASE, 0xffffc100 #RGB LED 1 .equ SPILED_REG_LED_RGB1, 0xffffc110 .equ SPILED_REG_LED_RGB1_o, 0x0010 #RGB LED 2 .equ SPILED_REG_LED_RGB2, 0xffffc114 .equ SPILED_REG_LED_RGB2_o, 0x0014 #Three 8 bit Knobs #the highest byte used for knobs press .equ SPILED_REG_KNOBS_8BIT, 0xffffc124 .equ SPILED_REG_KNOBS_8BIT_o, 0x0024 #32 LED line .equ SPILED_REG_LED_LINE, 0xffffc104 .equ SPILED_REG_LED_LINE_o, 0x0004 li a0, SPILED_REG_BASE # a0 points to I/O memory area ori t2, t2, -1 loop: lw t0, SPILED_REG_KNOBS_8BIT_o(a0) # read data from knobs sw t0, SPILED_REG_LED_RGB1_o(a0) xor t1, t0, t2 sw t1, SPILED_REG_LED_RGB2_o(a0) srli t0, t0, 24 andi t0, t0, 4 beq t0, zero, loop # is red knob pressed ebreak # end program
Serial terminal writing Peripherals:
li t0, 0xffffc000 // base address into memory mapped I/O area addi t1, zero, 48 addi t6, zero, 1234 addi t2, zero, 10 loop: lw t3, 0x08(t0) andi t3, t3, 1 beq t3, zero, loop sw t1, 0x0c(t0) addi t1, t1, 1 addi t2, t2, -1 bne t2, zero, loop ebreak
Serial line echoing:
li t0, 0xffffc000 // base address into memory mapped I/O area addi t1, zero, 48 addi t6, zero, 1234 addi t2, zero, 10 loop_rx: lw t3, 0x0(t0) andi t3, t3, 1 beq t3, zero, loop_rx lw t1, 4(t0) loop_tx: lw t3, 0x08(t0) andi t3, t3, 1 beq t3, zero, loop_tx sw t1, 0x0c(t0) addi t1, t1, 1 addi t2, t2, -1 bne t2, zero, loop_rx ebreak
LED line:
lui t0, 0xffffc ori t0, t0, 0x100 addi t1, zero, 5 loop: sw t1, 4(t0) slli t1, t1, 1 bne t1, zero, loop ebreak
LED line
#define _POSIX_C_SOURCE 200112L #include <stdlib.h> #include <stdio.h> #include <stdint.h> #include <time.h> #include <unistd.h> #include "mzapo_parlcd.h" #include "mzapo_phys.h" #include "mzapo_regs.h" int main(int argc, char *argv[]) { unsigned char *mem_base; uint32_t val_line=5; int i; printf("Hello world\n"); sleep(1); /* * Setup memory mapping which provides access to the peripheral * registers region of RGB LEDs, knobs and line of yellow LEDs. */ mem_base = map_phys_address(SPILED_REG_BASE_PHYS, SPILED_REG_SIZE, 0); /* If mapping fails exit with error code */ if (mem_base == NULL) exit(1); for (i=0; i<30; i++) { *(volatile uint32_t*)(mem_base + SPILED_REG_LED_LINE_o) = val_line; val_line<<=1; printf("LED val 0x%x\n", val_line); sleep(1); } printf("Goodbye world\n"); return 0; }
Knobs and led line
/******************************************************************* Project main function template for MicroZed based MZ_APO board designed by Petr Porazil at PiKRON change_me.c - main file include your name there and license for distribution. Remove next text: This line should not appear in submitted work and project name should be change to match real application. If this text is there I want 10 points subtracted from final evaluation. *******************************************************************/ #define _POSIX_C_SOURCE 200112L #include <stdlib.h> #include <stdio.h> #include <stdint.h> #include <time.h> #include <unistd.h> #include "mzapo_parlcd.h" #include "mzapo_phys.h" #include "mzapo_regs.h" #include "serialize_lock.h" int main(int argc, char *argv[]) { unsigned char *mem_base; uint32_t val_line=0x5; int i; struct timespec loop_delay; loop_delay.tv_sec = 0; loop_delay.tv_nsec = 50 * 1000 * 1000; printf("Hello world\n"); sleep(1); /* * Setup memory mapping which provides access to the peripheral * registers region of RGB LEDs, knobs and line of yellow LEDs. */ mem_base = map_phys_address(SPILED_REG_BASE_PHYS, SPILED_REG_SIZE, 0); /* If mapping fails exit with error code */ if (mem_base == NULL) exit(1); while (1) { uint32_t knobs = *(volatile uint32_t*) (mem_base + SPILED_REG_KNOBS_8BIT_o); int blue_knob = (knobs & 0xff); int pos_pat = (blue_knob * 29)/255; val_line = 5<<pos_pat; *(volatile uint32_t*)(mem_base + SPILED_REG_LED_LINE_o) = val_line; printf("LED val 0x%x\n", val_line); clock_nanosleep(CLOCK_MONOTONIC, 0, &loop_delay, NULL); } printf("Goodbye world\n"); return 0; }
LCD example moving_square.c:
/******************************************************************* Project main function template for MicroZed based MZ_APO board designed by Petr Porazil at PiKRON include your name there and license for distribution. Remove next text: This line should not appear in submitted work and project name should be change to match real application. If this text is there I want 10 points subtracted from final evaluation. *******************************************************************/ #define _POSIX_C_SOURCE 200112L #include <stdlib.h> #include <stdio.h> #include <stdint.h> #include <time.h> #include <unistd.h> #include <termios.h> //termios, TCSANOW, ECHO, ICANON #include "mzapo_parlcd.h" #include "mzapo_phys.h" #include "mzapo_regs.h" unsigned short *fb; void draw_pixel(int x, int y, unsigned short color) { if (x>=0 && x<480 && y>=0 && y<320) { fb[x+480*y] = color; } } int main(int argc, char *argv[]) { unsigned char *parlcd_mem_base, *mem_base; int i,j; int ptr; unsigned int c; fb = (unsigned short *)malloc(320*480*2); printf("Hello world\n"); parlcd_mem_base = map_phys_address(PARLCD_REG_BASE_PHYS, PARLCD_REG_SIZE, 0); if (parlcd_mem_base == NULL) exit(1); mem_base = map_phys_address(SPILED_REG_BASE_PHYS, SPILED_REG_SIZE, 0); if (mem_base == NULL) exit(1); parlcd_hx8357_init(parlcd_mem_base); parlcd_write_cmd(parlcd_mem_base, 0x2c); ptr=0; for (i = 0; i < 320 ; i++) { for (j = 0; j < 480 ; j++) { c = 0; fb[ptr]=c; parlcd_write_data(parlcd_mem_base, fb[ptr++]); } } struct timespec loop_delay; loop_delay.tv_sec = 0; loop_delay.tv_nsec = 150 * 1000 * 1000; int xx=0, yy=0; while (1) { int r = *(volatile uint32_t*)(mem_base + SPILED_REG_KNOBS_8BIT_o); if ((r&0x7000000)!=0) { break; } xx = ((r&0xff)*480)/256; yy = (((r>>8)&0xff)*320)/256; for (ptr = 0; ptr < 320*480 ; ptr++) { fb[ptr]=0u; } for (j=0; j<60; j++) { for (i=0; i<60; i++) { draw_pixel(i+xx,j+yy,0x7ff); } } parlcd_write_cmd(parlcd_mem_base, 0x2c); for (ptr = 0; ptr < 480*320 ; ptr++) { parlcd_write_data(parlcd_mem_base, fb[ptr]); } clock_nanosleep(CLOCK_MONOTONIC, 0, &loop_delay, NULL); } parlcd_write_cmd(parlcd_mem_base, 0x2c); for (ptr = 0; ptr < 480*320 ; ptr++) { parlcd_write_data(parlcd_mem_base, 0); } printf("Goodbye world\n"); return 0; }
flying_letters.c:
/******************************************************************* Project main function template for MicroZed based MZ_APO board designed by Petr Porazil at PiKRON include your name there and license for distribution. Remove next text: This line should not appear in submitted work and project name should be change to match real application. If this text is there I want 10 points subtracted from final evaluation. *******************************************************************/ #define _POSIX_C_SOURCE 200112L #include <stdlib.h> #include <stdio.h> #include <stdint.h> #include <time.h> #include <unistd.h> #include <math.h> #include "mzapo_parlcd.h" #include "mzapo_phys.h" #include "mzapo_regs.h" #include "font_types.h" #define M_PI 3.1415 unsigned int hsv2rgb_lcd(int hue, int saturation, int value) { hue = (hue%360); float f = ((hue%60)/60.0); int p = (value*(255-saturation))/255; int q = (value*(255-(saturation*f)))/255; int t = (value*(255-(saturation*(1.0-f))))/255; unsigned int r,g,b; if (hue < 60){ r = value; g = t; b = p; } else if (hue < 120) { r = q; g = value; b = p; } else if (hue < 180) { r = p; g = value; b = t; } else if (hue < 240) { r = p; g = q; b = value; } else if (hue < 300) { r = t; g = p; b = value; } else { r = value; g = p; b = q; } r>>=3; g>>=2; b>>=3; return (((r&0x1f)<<11)|((g&0x3f)<<5)|(b&0x1f)); } unsigned short fb[320*480*2]; font_descriptor_t *fdes; int scale=4; void draw_pixel(int x, int y, unsigned short color) { if (x>=0 && x<480 && y>=0 && y<320) { fb[x+480*y] = color; } } void draw_pixel_big(int x, int y, unsigned short color) { int i,j; for (i=0; i<scale; i++) { for (j=0; j<scale; j++) { draw_pixel(x+i, y+j, color); } } } int char_width(int ch) { int width; if (!fdes->width) { width = fdes->maxwidth; } else { width = fdes->width[ch-fdes->firstchar]; } return width; } void draw_char(int x, int y, char ch, unsigned short color) { int w = char_width(ch); const font_bits_t *ptr; if ((ch >= fdes->firstchar) && (ch-fdes->firstchar < fdes->size)) { if (fdes->offset) { ptr = &fdes->bits[fdes->offset[ch-fdes->firstchar]]; } else { int bw = (fdes->maxwidth+15)/16; ptr = &fdes->bits[(ch-fdes->firstchar)*bw*fdes->height]; } int i, j; for (i=0; i<fdes->height; i++) { font_bits_t val = *ptr; for (j=0; j<w; j++) { if ((val&0x8000)!=0) { draw_pixel_big(x+scale*j, y+scale*i, color); } val<<=1; } ptr++; } } } int main(int argc, char *argv[]) { unsigned char *parlcd_mem_base; int i,j; printf("Hello\n"); parlcd_mem_base = map_phys_address(PARLCD_REG_BASE_PHYS, PARLCD_REG_SIZE, 0); if (parlcd_mem_base == NULL) exit(1); parlcd_hx8357_init(parlcd_mem_base); parlcd_write_cmd(parlcd_mem_base, 0x2c); for (i = 0; i < 320 ; i++) { for (j = 0; j < 480 ; j++) { parlcd_write_data( parlcd_mem_base, hsv2rgb_lcd(j, 255, (i*255)/320)); } } sleep(5); int k; int ptr; struct timespec loop_delay = {.tv_sec = 0, .tv_nsec = 120 * 1000 * 1000}; fdes = &font_winFreeSystem14x16; float g=1.0; for (k=0; k<=80; k+=5) { float alfa=((10+k)*M_PI)/180.0; float vx=32*(M_PI/2.0-alfa); float vy=32*(2.0*alfa/M_PI); float x=1; float y=1; char ch=('a'+k/5); printf("Flying:%c\n",ch); unsigned int col=hsv2rgb_lcd(4*k,255,255); while ((x<480) && (y>0)) { for (ptr = 0; ptr < 320*480 ; ptr++) { fb[ptr]=0; } draw_char((int)x,250-(int)y, ch, col); x+=vx; y+=vy; vx = vx*0.97; vy = vy*0.97-g; parlcd_write_cmd(parlcd_mem_base, 0x2c); for (ptr = 0; ptr < 480*320 ; ptr++) { parlcd_write_data(parlcd_mem_base, fb[ptr]); } clock_nanosleep(CLOCK_MONOTONIC, 0, &loop_delay, NULL); } } ptr=0; parlcd_write_cmd(parlcd_mem_base, 0x2c); for (i = 0; i < 320 ; i++) { for (j = 0; j < 480 ; j++) { fb[ptr]=0; parlcd_write_data(parlcd_mem_base, fb[ptr++]); } } printf("Goodbye\n"); return 0; }
Circuit realization of I/O device on PCI and more modern is too complex for the introductory course like ours. For our educational purposes it is more suitable to show you circuit realization of old ISA bus.
Address decoder:
Simple I/O device:
lspci
lspci -xxx
In lectures you have seen examples of building blocks usable for PCI device, including control finite state automaton. Extend this design to add a configuration read and write. (A diagram for config read and write: )