diff --git a/devices/ioctrl/amic.cpp b/devices/ioctrl/amic.cpp
index 158a7c3..213cf85 100644
--- a/devices/ioctrl/amic.cpp
+++ b/devices/ioctrl/amic.cpp
@@ -123,6 +123,8 @@ uint32_t AMIC::read(uint32_t reg_start, uint32_t offset, int size)
}
switch(offset) {
+ case AMICReg::Ariel_Config:
+ return this->def_vid->get_vdac_config();
case AMICReg::Video_Mode:
return this->def_vid->get_video_mode();
case AMICReg::Monitor_Id:
@@ -223,7 +225,7 @@ void AMIC::write(uint32_t reg_start, uint32_t offset, uint32_t value, int size)
this->def_vid->set_clut_color(value);
break;
case AMICReg::Ariel_Config:
- this->def_vid->vdac_config(value);
+ this->def_vid->set_vdac_config(value);
break;
case AMICReg::Video_Mode:
this->def_vid->set_video_mode(value);
diff --git a/devices/video/pdmonboard.cpp b/devices/video/pdmonboard.cpp
index d546f86..1e8a1f6 100644
--- a/devices/video/pdmonboard.cpp
+++ b/devices/video/pdmonboard.cpp
@@ -21,6 +21,7 @@ along with this program. If not, see .
/** @file PDM on-board video emulation. */
+#include
#include
#include
#include
@@ -33,10 +34,11 @@ along with this program. If not, see .
PdmOnboardVideo::PdmOnboardVideo()
: VideoCtrlBase()
{
- this->video_mode = PDM_VMODE_OFF;
- this->blanking = 0x80;
- this->crtc_on = false;
- this->vdac_mode = 8;
+ this->video_mode = PDM_VMODE_OFF;
+ this->blanking = 0x80;
+ this->crtc_on = false;
+ this->vdac_mode = 8;
+ this->pixel_depth = 0;
// get pointer to the Highspeed Memory controller
this->hmc_obj = dynamic_cast(gMachineObj->get_comp_by_name("HMC"));
@@ -75,18 +77,24 @@ void PdmOnboardVideo::set_pixel_depth(uint8_t depth)
{
static uint8_t pix_depths[8] = {1, 2, 4, 8, 16, 0xFF, 0xFF, 0xFF};
- this->pixel_depth = pix_depths[depth];
- if (this->pixel_depth == 0xFF) {
+ uint8_t new_pix_depth = pix_depths[depth];
+ if (new_pix_depth == 0xFF) {
ABORT_F("PDM-Video: invalid pixel depth code %d specified!", depth);
}
+
+ if (new_pix_depth != this->pixel_depth) {
+ this->pixel_depth = new_pix_depth;
+ this->set_depth_internal(this->active_width);
+ LOG_F(INFO, "PDM-Video: pixel depth changed to %dbpp", new_pix_depth);
+ }
}
-void PdmOnboardVideo::vdac_config(uint8_t mode)
+void PdmOnboardVideo::set_vdac_config(uint8_t mode)
{
- if (mode != 8) {
- LOG_F(WARNING, "Unknown Ariel Config code 0x%X", mode);
+ this->vdac_mode = mode;
+ if ((mode & 0xF8) != 8) {
+ LOG_F(WARNING, "Ariel control changed to unknown value 0x%X", mode);
}
- this->vdac_mode = 8; // 1 bpp, master mode, no overlay
}
void PdmOnboardVideo::set_clut_index(uint8_t index)
@@ -110,9 +118,29 @@ void PdmOnboardVideo::set_clut_color(uint8_t color)
}
}
+void PdmOnboardVideo::set_depth_internal(int pitch)
+{
+ switch (this->pixel_depth) {
+ case 1:
+ this->convert_fb_cb = [this](uint8_t* dst_buf, int dst_pitch) {
+ this->convert_frame_1bpp(dst_buf, dst_pitch);
+ };
+ this->fb_pitch = pitch >> 3; // one byte contains 8 pixels
+ break;
+ case 8:
+ this->convert_fb_cb = [this](uint8_t* dst_buf, int dst_pitch) {
+ this->convert_frame_8bpp(dst_buf, dst_pitch);
+ };
+ this->fb_pitch = pitch; // one byte contains 1 pixel
+ break;
+ default:
+ ABORT_F("PDM-Video: pixel depth %d not implemented yet!", this->pixel_depth);
+ }
+}
+
void PdmOnboardVideo::enable_video_internal()
{
- int new_width, new_height;
+ int new_width, new_height, hori_blank, vert_blank;
// ensure all video parameters contain safe values
switch(this->video_mode) {
@@ -131,26 +159,36 @@ void PdmOnboardVideo::enable_video_internal()
case PdmVideoMode::Portrait:
new_width = 640;
new_height = 870;
+ hori_blank = 192;
+ vert_blank = 48;
this->pixel_clock = 57283200;
break;
case PdmVideoMode::Rgb12in:
new_width = 512;
new_height = 384;
+ hori_blank = 128;
+ vert_blank = 23;
this->pixel_clock = 15667200;
break;
case PdmVideoMode::Rgb13in:
new_width = 640;
new_height = 480;
+ hori_blank = 256;
+ vert_blank = 45;
this->pixel_clock = 31334400;
break;
case PdmVideoMode::Rgb16in:
new_width = 832;
new_height = 624;
+ hori_blank = 320;
+ vert_blank = 43;
this->pixel_clock = 57283200;
break;
case PdmVideoMode::VGA:
new_width = 640;
new_height = 480;
+ hori_blank = 160;
+ vert_blank = 45;
this->pixel_clock = 25175000;
break;
default:
@@ -171,16 +209,18 @@ void PdmOnboardVideo::enable_video_internal()
this->active_width = new_width;
this->active_height = new_height;
- switch(this->pixel_depth) {
- case 1:
- this->convert_fb_cb = [this](uint8_t *dst_buf, int dst_pitch) {
- this->convert_frame_1bpp(dst_buf, dst_pitch);
- };
- this->fb_pitch = new_width >> 3; // one byte contains 8 pixels
- break;
- default:
- ABORT_F("PDM-Video: pixel depth %d not implemented yet!", this->pixel_depth);
- }
+ this->set_depth_internal(new_width);
+
+ // set up video refresh timer
+ double refresh_rate_hz = (double)(this->pixel_clock) / (new_width + hori_blank) / (new_height + vert_blank);
+ LOG_F(INFO, "PDM-Video: refresh rate set to %f Hz", refresh_rate_hz);
+ uint64_t refresh_interval = static_cast(1.0f / refresh_rate_hz * NS_PER_SEC + 0.5);
+ TimerManager::get_instance()->add_cyclic_timer(
+ refresh_interval,
+ [this]() {
+ this->update_screen();
+ }
+ );
this->update_screen();
diff --git a/devices/video/pdmonboard.h b/devices/video/pdmonboard.h
index 4665465..03e735a 100644
--- a/devices/video/pdmonboard.h
+++ b/devices/video/pdmonboard.h
@@ -54,11 +54,15 @@ public:
void set_video_mode(uint8_t new_mode);
void set_pixel_depth(uint8_t depth);
- void vdac_config(uint8_t config);
+ void set_vdac_config(uint8_t config);
+ uint8_t get_vdac_config() {
+ return this->vdac_mode;
+ };
void set_clut_index(uint8_t index);
void set_clut_color(uint8_t color);
protected:
+ void set_depth_internal(int pitch);
void enable_video_internal();
void disable_video_internal();
void convert_frame_1bpp(uint8_t *dst_buf, int dst_pitch);