Skip to content

Commit

Permalink
Merge branch 'classroom_hrdwdisplay' into draft
Browse files Browse the repository at this point in the history
  • Loading branch information
sylefeb committed Dec 7, 2023
2 parents 00545d8 + 2a93fce commit aa9fb32
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 14 deletions.
13 changes: 12 additions & 1 deletion learn-silice/classroom/soc_wave_player/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,17 @@ endif
step6.si : hardware/main.si
python ../tools/solutions.py -i hardware/main.si -s LED,AUDIO,SCREEN,BTN,SD,STREAM > $@

step7: step7.si
make -C firmware $(FIRMWARE) DEFINES="-DHWFBUFFER"
ifeq ($(BOARD),verilator)
silice-make.py -s [email protected] -b $(BOARD) -p basic,oled -o BUILD_$(subst :,_,$@) $(ARGS)
else
silice-make.py -s [email protected] -b $(BOARD) -p basic,audio,oled,buttons,sdcard -o BUILD_$(subst :,_,$@) $(ARGS)
endif

step7.si : hardware/main.si
python ../tools/solutions.py -i hardware/main.si -s LED,AUDIO,SCREEN,BTN,SD,STREAM,HWFBUFFER > $@

final: final.si
make -C firmware $(FIRMWARE)
ifeq ($(BOARD),verilator)
Expand All @@ -87,7 +98,7 @@ else
endif

final.si : hardware/main.si
python ../tools/solutions.py -i hardware/main.si -s LED,AUDIO,SCREEN,BTN,SD,STREAM,PWM > $@
python ../tools/solutions.py -i hardware/main.si -s LED,AUDIO,SCREEN,BTN,SD,STREAM,HWFBUFFER,PWM > $@

clean:
make -C firmware clean
Expand Down
2 changes: 1 addition & 1 deletion learn-silice/classroom/soc_wave_player/firmware/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ $(PRGS): %: %.o $(OBJS)
$(ARCH)-objdump --disassemble code.elf > code.s

%.o : %.c
$(CC) -fno-builtin -fno-unroll-loops -Os -fno-stack-protector -fno-pic -march=rv32i -mabi=ilp32 -c $< -o $@
$(CC) -fno-builtin -fno-unroll-loops $(DEFINES) -Os -fno-stack-protector -fno-pic -march=rv32i -mabi=ilp32 -c $< -o $@

%.o : %.s
$(AS) -march=rv32i -mabi=ilp32 $< -o $@
Expand Down
1 change: 1 addition & 0 deletions learn-silice/classroom/soc_wave_player/firmware/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ volatile int* const OLED_RST = (int*)0x10010; // 10000000000010000
volatile int* const UART = (int*)0x10020; // 10000000000100000
volatile int* const SDCARD = (int*)0x10080; // 10000000010000000
volatile int* const BUTTONS = (int*)0x10100; // 10000000100000000
volatile int* const DISPLAY = (int*)0x14000; // 10100000000000000
volatile int* const AUDIO = (int*)0x18000; // 11000000000000000
1 change: 1 addition & 0 deletions learn-silice/classroom/soc_wave_player/firmware/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ extern volatile int* const UART;
extern volatile int* const SDCARD;
extern volatile int* const AUDIO;
extern volatile int* const BUTTONS;
extern volatile int* const DISPLAY;
8 changes: 7 additions & 1 deletion learn-silice/classroom/soc_wave_player/firmware/display.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,13 @@ int cursor_y;
unsigned char front_color;
unsigned char back_color;

#ifdef HWFBUFFER
#define framebuffer ((volatile unsigned char *)DISPLAY)
#else
unsigned char framebuffer[128*128];
#endif

unsigned char *display_framebuffer()
volatile unsigned char *display_framebuffer()
{
return framebuffer;
}
Expand Down Expand Up @@ -61,13 +65,15 @@ void display_putchar(int c)

void display_refresh()
{
#ifndef HWFBUFFER
unsigned char *ptr = framebuffer;
for (int i=0;i<128*128;i++) {
unsigned char c = (*ptr)>>2;
++ ptr;
oled_pix(c,c,c);
oled_wait();
}
#endif
}

void dual_putchar(int c)
Expand Down
2 changes: 1 addition & 1 deletion learn-silice/classroom/soc_wave_player/firmware/display.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ void display_set_front_back_color(unsigned char f,unsigned char b);
void display_putchar(int c);
void display_refresh();
void dual_putchar(int c);
unsigned char *display_framebuffer();
volatile unsigned char *display_framebuffer();
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// @sylefeb 2022-01-10
// MIT license, see LICENSE_MIT in Silice repo root
// https://github.com/sylefeb/Silice/

#include "config.h"
#include "std.h"
#include "oled.h"
#include "display.h"
#include "printf.h"

#ifndef HWFBUFFER
#error This firmware needs HWFBUFFER defined
#endif

void main()
{
// install putchar handler for printf
f_putchar = display_putchar;
// init display
oled_init();
oled_fullscreen();
oled_clear(0);
// print message
display_set_cursor(0,0);
display_set_front_back_color(255,0);

// gradient background
for (int i = 0 ; i < 128; ++i) {
for (int j = 0 ; j < 128; ++j) {
display_framebuffer()[i + (j << 7)] = i;
}
}

// bouncing text
int dx = 3;
int dy = 1;
int x = 0;
int y = 0;
while (1) {
display_set_cursor(x,y);
printf("Hello world!");
x += dx;
if (x > 64) {
x = 64;
dx = -dx;
} else if (x < 0) {
x = 0;
dx = -dx;
}
y += dy;
if (y > 108) {
y = 108;
y = -dy;
} else if (y < 0) {
y = 0;
dy = -dy;
}
}

}
64 changes: 54 additions & 10 deletions learn-silice/classroom/soc_wave_player/hardware/main.si
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ $$if not Solution_PWM then
}
$$else
uint8 counter = 0;
uint4 low = 4b0;
uint4 high = 4b1;
uint4 low = 0;
uint4 high = 15;
always {
uint8 frac = audio_in;
audio_out = counter < frac ? high : low;
Expand Down Expand Up @@ -129,16 +129,20 @@ $$end

$$if Solution_SCREEN then
// SPIscreen (OLED) controller chip
uint1 displ_dta_or_cmd <: prev_wdata[10,1];
uint8 displ_byte <: prev_wdata[0,8];
oled display(
data_or_command <: displ_dta_or_cmd,
byte <: displ_byte,
oled_din :> oled_mosi,
oled_clk :> oled_clk,
oled_dc :> oled_dc,
);
$$end
$$if Solution_HWFBUFFER then
// allocate a BRAM for the display pixels
simple_dualport_bram uint8 frame_buffer[$128*128$] = uninitialized;
uint1 fb_enabled = 0;
uint14 fb_pixcount = 0;
uint3 fb_channel = 3b010;
uint17 fb_wait = 1;
$$end

$$if Solution_SPIflash then
$$if not SPIFLASH then
Expand Down Expand Up @@ -243,6 +247,22 @@ $$if Solution_STREAM then
: (audio_buffer_sample+1) // go to next sample
);
audio_counter = (audio_counter == $PERIOD$) ? 0 : (audio_counter+1);
$$end
$$if Solution_HWFBUFFER then
// ---- hardware display buffer
frame_buffer.wenable1 = 0;
display.enable = fb_enabled & fb_wait[0,1];
display.data_or_command = 1;
display.byte = frame_buffer.rdata0;
frame_buffer.addr0 = fb_pixcount;
fb_channel = (fb_enabled & fb_wait[0,1])
? {fb_channel[0,2],fb_channel[2,1]}
: fb_channel;
fb_wait = (fb_enabled) ? {fb_wait[0,16],fb_wait[16,1]}
: fb_wait;
fb_pixcount = (fb_enabled & fb_wait[0,1] & fb_channel[0,1])
? fb_pixcount + 1
: fb_pixcount;
$$end
// ---- check whether the CPU read from or wrote to a peripheral address
uint1 peripheral = prev_mem_addr[$periph_bit$,1];
Expand All @@ -255,7 +275,7 @@ $$if Solution_LED then
uint1 leds_access = prev_mem_addr[ 0,1];
$$end
$$if Solution_SCREEN then
uint1 display_en_access = prev_mem_addr[ 1,1];
uint1 display_direct_access = prev_mem_addr[ 1,1];
uint1 display_reset_access = prev_mem_addr[ 2,1];
$$end
$$if Solution_UART then
Expand All @@ -269,6 +289,9 @@ $$if Solution_SD then
$$end
$$if Solution_BTN then
uint1 button_access = prev_mem_addr[ 6,1];
$$end
$$if Solution_HWFBUFFER then
uint1 framebuffer_access = prev_mem_addr[$periph_bit-2$,1];
$$end
// ---- memory access CPU <-> BRAM (reads and writes)
// reads RAM, peripherals => CPU
Expand All @@ -295,19 +318,29 @@ $$end
ram.wdata = memio.wdata;
ram.addr = memio.addr;
// writes CPU => peripherals
$$if Solution_HWFBUFFER and Solution_STREAM then
if (peripheral_w & ~audio_access & ~framebuffer_access) {
$$else
$$if Solution_STREAM then
if (peripheral_w & ~audio_access) {
$$else
if (peripheral_w) {
$$end
$$end
$$if Solution_LED then
/// LEDs
leds = leds_access ? prev_wdata[0,8] : leds;
$$end
$$if Solution_SCREEN then
/// display
// -> whether to send command or data
display.enable = display_en_access & (prev_wdata[9,1] | prev_wdata[10,1]);
if (display_direct_access) {
// -> whether to send command or data
display.enable = (prev_wdata[9,1] | prev_wdata[10,1]);
// -> byte to send
display.byte = prev_wdata[0,8];
// -> data or command
display.data_or_command = prev_wdata[10,1];
}
// -> SPIscreen reset
oled_resn = ~ (display_reset_access & prev_wdata[0,1]);
$$end
Expand Down Expand Up @@ -366,16 +399,27 @@ $$if SIMULATION then
$$end
}

$$if Solution_STREAM then
$$if Solution_STREAM or Solution_HWFBUFFER then
if (peripheral_w) {
uint2 which = prev_mem_rw[1,2] | {2{prev_mem_rw[3,1]}};
// ^^^^^ produces 0,1,2,3 based on write mask
$$if Solution_STREAM then
// ---- audio
audio_buffer.wdata1 = prev_wdata >> {which,3b0};
// ^^^ sample to be written ^^ (shift due to 32bits addressing)
audio_buffer.addr1 = audio_buffer_start_waddr
| {prev_mem_addr[0,7],2b0}//addr from CPU (32bits)
| which; // sample address
audio_buffer.wenable1 = audio_access; // write sample
$$end
$$if Solution_HWFBUFFER then
// ---- display
frame_buffer.wenable1 = framebuffer_access;
fb_enabled = fb_enabled | framebuffer_access;
frame_buffer.addr1 = {prev_mem_addr[0,12],which}; //addr from CPU (32bits)
uint8 clr = prev_wdata[{which,3b000},8]; // get 8 bit channel value
frame_buffer.wdata1 = {2b00,clr[2,6]}; // remap to 6 bits per channel
$$end
}
$$end

Expand Down

0 comments on commit aa9fb32

Please sign in to comment.