summaryrefslogtreecommitdiffstats
path: root/Graphic_Equalizer_v1.0/src/display.hcc
diff options
context:
space:
mode:
Diffstat (limited to 'Graphic_Equalizer_v1.0/src/display.hcc')
-rw-r--r--Graphic_Equalizer_v1.0/src/display.hcc475
1 files changed, 475 insertions, 0 deletions
diff --git a/Graphic_Equalizer_v1.0/src/display.hcc b/Graphic_Equalizer_v1.0/src/display.hcc
new file mode 100644
index 0000000..81d0037
--- /dev/null
+++ b/Graphic_Equalizer_v1.0/src/display.hcc
@@ -0,0 +1,475 @@
+/*! \file display.hcc
+ *
+ * \section generic Message build up information and more
+ *
+ * \section project Project information.
+ * Project Graphic Equalizer\n
+ * \author O.M. Schinagl
+ * \date 20041011
+ * \version 0.1
+ *
+ * \section copyright Copyright
+ * Copyright ©2004 Koninklijke Philips Electronics N.V. All rights reserved
+ *
+ * \section history Change history
+ * 20041011: O.M. Schinagl\n Initial version
+ *
+ ********************************************************************/
+
+/*
+ * Set the Clock rate for this domain. 25.175 Mhz is required for the Video output.
+ */
+#define PAL_TARGET_CLOCK_RATE 25175000
+
+/******** System Includes *************/
+#include <stdlib.hch>
+
+#include "pal_master.hch"
+
+/******** Application Includes ********/
+#include "configuration.hch"
+#include "audio.hch"
+#include "eventhandler_shared.hch"
+#include "mouse_shared.hch"
+#include "smartmedia_shared.hch"
+#include "display_shared.hch"
+#include "display.hch"
+
+#if HAVE_DEBUG
+ #include "debug.hch"
+#endif
+
+
+
+/*
+ * Channel to notify others when new mousedata is available. If so
+ * Then mousedata struct is updated with shared data.
+ */
+chan unsigned 1 maskupdate_notification;
+
+
+
+/*
+ */
+static rom unsigned 20 images[32] = {
+ ADDRESS_ABOUT_TOP_FONTYS_START,
+ ADDRESS_ABOUT_TOP_TASS_START,
+ ADDRESS_ABOUT_TOP_TRANSFER_START,
+ ADDRESS_ABOUT_TOP_CELOXICA_START,
+ ADDRESS_ABOUT_TOP_DETAILS_START,
+ ADDRESS_ABOUT_BOTTOM_START,
+ ADDRESS_SKIN_START,
+ ADDRESS_HELP_START,
+ ADDRESS_HELP_START,
+ ADDRESS_GRAPH_START
+};
+
+
+
+/*! \fn void display_main(skindata_t *skindata, audiodata_t *audiodata, events_t *events, mousedata_t *mousedata)
+ *
+ * \brief This routine handles all drawing of pixels. It never returns!
+ *
+ * \param *skindata struct with all skin information.
+ * \param *audiodata struct with (i)fft data to be drawn.
+ * \param *events struct with all events.
+ * \param *mousedata struct with coordinates to current.
+ * X en Y.
+ *
+ * \return Never Returns.
+ * \retval void
+ */
+inline void display_main(skindata_t *skindata, audiodata_t *audiodata, events_t *events, mousedata_t *mousedata) {
+ /*
+ * Setup macro's RAM/Video handles and to coordinate pixel writing.
+ */
+ macro expr CLOCKRATE = PAL_ACTUAL_CLOCK_RATE;
+ macro expr VIDEOOUT = PalVideoOutOptimalCT(CLOCKRATE);
+ macro expr RAM_BANK0 = PalPL2RAMCT(0);
+ macro expr DW = PalPL2RAMGetMaxDataWidthCT();
+ macro expr AW = PalPL2RAMGetMaxAddressWidthCT();
+ macro expr VISIBLEX = PalVideoOutGetVisibleX(VIDEOOUT, CLOCKRATE);
+ macro expr VISIBLEY = PalVideoOutGetVisibleY(VIDEOOUT);
+ macro expr TOTALX = PalVideoOutGetTotalX(VIDEOOUT, CLOCKRATE);
+ macro expr TOTALY = PalVideoOutGetTotalY(VIDEOOUT);
+ macro expr SCANX = PalVideoOutGetX(VIDEOOUT);
+ macro expr SCANY = PalVideoOutGetY(VIDEOOUT);
+
+ unsigned AW addresses[32];
+ unsigned DW pixeldata;
+ unsigned 24 visual_graph_color;
+ unsigned 5 address_index;
+
+
+
+ /*
+ * The passed button_state tells us if the button is active, then we
+ * the button is 'on' and we draw it inverted. Otherwise we draw the
+ * area of the button normally.
+ */
+ macro proc draw_button(button_state) {
+ if (button_state) {
+ PalVideoOutWrite(VIDEOOUT, ~PIXEL);
+ } else {
+ PalVideoOutWrite(VIDEOOUT, PIXEL);
+ }
+ }
+
+ /*
+ * Prime Rendering Pipeline to start where the skin starts.
+ */
+ PalPL2RAMSetReadAddress(RAM_BANK0, images[events->image]);
+
+ /*
+ * Run the following tasks indefinatly and in parallel
+ */
+ while (TRUE) {
+ par {
+ /*
+ * Before starting this loop we allready set the the
+ * address. Therefor we can start reading the
+ * previously set address and prepare the next address
+ * for the next cycle.
+ */
+ PalPL2RAMRead(RAM_BANK0, &pixeldata);
+ PalPL2RAMSetReadAddress(RAM_BANK0, (IMAGE_GRAPH == events->image) ? (images[events->image] +(0 @ (addresses[address_index] \\ 2))) : (images[events->image] +addresses[address_index]));
+
+ /*
+ * Always reset the address_index to the corresponding
+ * array index containing the address counter of the
+ * background image, when the default skin should be
+ * displayed.
+ */
+ if (IMAGE_SKIN == events->image) {
+ address_index = MASK_AREA_BACKGROUND;
+ } else {
+ delay;
+ }
+
+ /*
+ * When displaying the visual the pixeldata read
+ * from the RAM-bank needs to be interpreted differntly,
+ * since the visual-image is not stored as a MRGB value,
+ * but as a MMMM-value. (M = mask)
+ */
+ if (IMAGE_GRAPH == events->image) {
+ par {
+ switch (addresses[MASK_AREA_BACKGROUND] <- 2) {
+ case 3:
+ visual_graph_color = ((unsigned 8)(0 @ audiodata->fft_info.read[pixeldata[31:24]]) << 1) @ ((unsigned 8)(0 @ audiodata->fft_info.read[pixeldata[31:24]]) << -1) @ ((unsigned 8)(0 @ audiodata->fft_info.read[pixeldata[31:24]]) << 0);
+ break;
+ case 0:
+ visual_graph_color = ((unsigned 8)(0 @ audiodata->fft_info.read[pixeldata[23:16]]) << 1) @ ((unsigned 8)(0 @ audiodata->fft_info.read[pixeldata[23:16]]) << -1) @ ((unsigned 8)(0 @ audiodata->fft_info.read[pixeldata[23:16]]) << 0);
+ break;
+ case 1:
+ visual_graph_color = ((unsigned 8)(0 @ audiodata->fft_info.read[pixeldata[15:8]]) << 1) @ ((unsigned 8)(0 @ audiodata->fft_info.read[pixeldata[15:8]]) << -1) @ ((unsigned 8)(0 @ audiodata->fft_info.read[pixeldata[15:8]]) << 0);
+ break;
+ case 2:
+ visual_graph_color = ((unsigned 8)(0 @ audiodata->fft_info.read[pixeldata[7:0]]) << 1) @ ((unsigned 8)(0 @ audiodata->fft_info.read[pixeldata[7:0]]) << -1) @ ((unsigned 8)(0 @ audiodata->fft_info.read[pixeldata[7:0]]) << 0);
+ break;
+ default:
+ delay;
+ break;
+ }
+
+ PalVideoOutWrite(VIDEOOUT, 0 @ visual_graph_color);
+ }
+ } else {
+ /*
+ * Determin what to draw where here. Every case has an
+ * if else statement comparing wether to draw something
+ * special or the background. Every specific drawing
+ * obviously only happens in the masked area.
+ */
+ switch (MASK) {
+ /*
+ */
+ case AREA_WAVEFORM:
+ if (SCANY == 0 @ skindata->waveform.bottom -(0 @ (audiodata->ifft_info.read[((SCANX -(0 @ skindata->waveform.left)) <-8)]))) {
+ PalVideoOutWrite(VIDEOOUT, skindata->waveform.color_primary);
+ } else {
+ PalVideoOutWrite(VIDEOOUT, PIXEL);
+ }
+ break;
+
+ /*
+ * Volume control over the Y-axis.
+ */
+ case AREA_VOLUME_YAXIS:
+ /*
+ * The volume_position stores
+ * the highest point of our
+ * bar. Every pixel after this
+ * point is drawn.
+ */
+ if (SCANY >= 0 @ events->volume_position) {
+ PalVideoOutWrite(VIDEOOUT, skindata->volume.color_primary);
+ } else {
+ PalVideoOutWrite(VIDEOOUT, PIXEL);
+ }
+ break;
+
+ /*
+ * Inputgain control over the Y-axis.
+ */
+ case AREA_INPUTGAIN_YAXIS:
+ /*
+ * The inputgain_position
+ * stores the highest point of
+ * our bar. Every pixel after
+ * this point is drawn.
+ */
+ if (SCANY >= 0 @ events->inputgain_position) {
+ PalVideoOutWrite(VIDEOOUT, (events->locked_gain) ? DISABLED : (events->saturated ? skindata->inputgain.color_secondary : skindata->inputgain.color_primary));
+ } else {
+ PalVideoOutWrite(VIDEOOUT, PIXEL);
+ }
+ break;
+
+ /*
+ * Spectrum Analyzer
+ */
+ case AREA_SPECTRUM_ANALYZER:
+ /*
+ * We draw every pixel that is smaller TODO
+ */
+ if ((SCANY >= (0 @ skindata->spectrum.bottom) -(0 @ audiodata->fft_info.read[(SCANX -(0 @ skindata->spectrum.left))[9:2]])) && ((SCANX -(0 @ skindata->spectrum.left)) <- 2)) {
+ PalVideoOutWrite(VIDEOOUT, PIXEL_SPECTRUM);
+ } else {
+ PalVideoOutWrite(VIDEOOUT, PIXEL);
+ }
+ break;
+
+ /*
+ * Since all buttons are drawn equally, either
+ * we draw them normally or we inverse them, we
+ * can handle them almost equally.
+ */
+ case BUTTON_PRESET_1: /* fall through */
+ case BUTTON_PRESET_2: /* fall through */
+ case BUTTON_PRESET_3: /* fall through */
+ case BUTTON_PRESET_4: /* fall through */
+ case BUTTON_PRESET_5: /* fall through */
+ case BUTTON_PRESET_6:
+ /*
+ * The active preset tells us what
+ * button is currently enabled. We must
+ * however not forget to add the preset
+ * button offset to possibly match it
+ * with the current mask.
+ */
+ draw_button(((events->active_preset +BUTTON_PRESET_1) <- 8)== MASK);
+ break;
+
+ case BUTTON_PRECISE: /* fall through */
+ case BUTTON_CONVEX_HALF: /* fall through */
+ case BUTTON_CONVEX_FULL:
+ /*
+ * equalizer mode tells us what button
+ * is currently enabled. By adding the
+ * equalizer mode button offset we can
+ * safley check wether it matches our
+ * mask.
+ */
+ draw_button(((0 @ events->equalizer_mode) +BUTTON_PRECISE) == MASK);
+ break;
+
+ case BUTTON_LOG:
+ /*
+ *
+ */
+ draw_button(audiodata->display_log);
+ break;
+
+ case BUTTON_PLAY:
+ draw_button(audiodata->play);
+ break;
+
+ case BUTTON_DEMO:
+ draw_button(events->button_demo_state);
+ break;
+ case BUTTON_RESET:
+ draw_button(events->button_reset_state);
+ break;
+
+ case BUTTON_HELP:
+ draw_button(events->image == IMAGE_HELP);
+ break;
+ case BUTTON_ABOUT:
+ draw_button(events->image == IMAGE_ABOUT);
+ break;
+
+ case AREA_ABOUT_TOP:
+ if (IMAGE_ABOUT == events->image) {
+ par {
+ events->image = events->image_about;
+ address_index = MASK_AREA_ABOUT_TOP;
+ PalVideoOutWrite(VIDEOOUT, PIXEL);
+ }
+ } else {
+ PalVideoOutWrite(VIDEOOUT, PIXEL);
+ }
+ break;
+
+ case BUTTON_URL_FONTYS: /* fall through */
+ case BUTTON_URL_TASS: /* fall through */
+ case BUTTON_URL_TRANSFER: /* fall through */
+ case BUTTON_URL_CELOXICA: /* fall through */
+ case BUTTON_URL_DETAILS: /* fall through */
+ case AREA_ABOUT_BOTTOM:
+ if (IMAGE_ABOUT == events->image) {
+ par {
+ events->image = IMAGE_ABOUT_BOTTOM;
+ address_index = MASK_AREA_ABOUT_BOTTOM;
+ PalVideoOutWrite(VIDEOOUT, PIXEL);
+ }
+ } else {
+ PalVideoOutWrite(VIDEOOUT, PIXEL);
+ }
+ break;
+
+ case AREA_MASK_END:
+ /* (IMAGE_ABOUT_TOP_FONTYS <= events->image) && (events->image <= IMAGE_ABOUT_BOTTOM)*/
+ if ((events->image <= IMAGE_ABOUT_BOTTOM) || (IMAGE_ABOUT == events->image)) {
+ par {
+ events->image = IMAGE_ABOUT;
+ address_index = MASK_AREA_BACKGROUND;
+ PalVideoOutWrite(VIDEOOUT, PIXEL);
+ }
+ } else {
+ PalVideoOutWrite(VIDEOOUT, PIXEL);
+ }
+ break;
+
+ /*
+ * The default case is split up into two parts
+ * actually. This is because we have 128 bands
+ * for the equalizer and thus as many mask
+ * entries. Since we don't want 128 identical
+ * cases we check wether the equalizer mask is
+ * currently active and if so draw it. If this
+ * is not the case we simply draw the
+ * background.
+ */
+ default:
+ /* (MASK <= AREA_EQUALIZER_MAX) && (AREA_EQUALIZER_MIN <= MASK) */
+ if ((AREA_EQUALIZER_MIN <= MASK) && (!events->locked_display)) {
+ if ((SCANY == 0 @ events->equalizer_display[(MASK -AREA_EQUALIZER_MIN) <- 7]) || ((SCANY +1) == 0 @ events->equalizer_display[(MASK -AREA_EQUALIZER_MIN) <- 7])) {
+ PalVideoOutWrite(VIDEOOUT, skindata->equalizer.color_primary);
+ } else {
+ PalVideoOutWrite(VIDEOOUT, PIXEL);
+ }
+ } else {
+ PalVideoOutWrite(VIDEOOUT, PIXEL);
+ }
+ break;
+ }
+ }
+
+
+ /*
+ * We compare our current X and Y scan positions of the
+ * output to the x and y data of the mouse. When those
+ * are equal we set the current mask to the mask stored
+ * in memory at that location. We then know what mask
+ * is to be used for events.
+ */
+ if (MOUSE_UPDATED == mousedata->status) {
+ if ((SCANX == 0 @ mousedata->x) && (SCANY == 0 @ mousedata->y)) {
+ par {
+ events->mask = MASK;
+ mousedata->status = MOUSE_NOT_UPDATED;
+ maskupdate_notification ! MOUSE_UPDATED;
+ }
+ } else {
+ delay;
+ }
+ } else {
+ delay;
+ }
+
+ /*
+ * The current position of the screen can lay in an
+ * area called the blanking area. We don't have data
+ * for this area as it is not drawn. We therefor have
+ * to determin wether we are beyond the visible area of
+ * the screen, but before the end of the total width of
+ * the screen. Our pipeline consists of 5 total stages.
+ * Therefor we have to substract 5 pixels.
+ */
+ if ((SCANX > (VISIBLEX - 5)) && (SCANX <= (TOTALX - 5))) {
+ par {
+ if (SCANY == (VISIBLEY +1)) {
+ par {
+ address_index++;
+ addresses[address_index] = 0;
+ }
+ } else {
+ delay;
+ }
+ /*
+ * We are in the blanking area of the screen.
+ * If we are on the last line, and thus last
+ * pixel we reset our address counter.
+ */
+ if (SCANY == (TOTALY -1)) {
+ /*
+ * Reset our draw address counter to 0.
+ */
+ par {
+ address_index = 0;
+ addresses[MASK_AREA_BACKGROUND] = 0;
+ }
+ } else {
+ /*
+ * We have reached the end of the
+ * visible line, but not the end of
+ * the screen. Therefore do nothing.
+ */
+ delay;
+ }
+ }
+ } else {
+ /*
+ * Increase the memory counter for each pixel
+ * drawn thus keeping the memory location in
+ * sync with the current pixel position.
+ */
+ par {
+ if (address_index != MASK_AREA_BACKGROUND) {
+ addresses[address_index]++;
+ } else {
+ delay;
+ }
+ addresses[MASK_AREA_BACKGROUND]++;
+ }
+ }
+ }
+ }
+} /* --- display_main() --- */
+
+
+
+/*! \fn void reload_equalizer(events_t *events, unsigned 4 *equalizer_levels)
+
+ * \brief This function copies the supplied equalizer values to the array
+ * used for displaying equalizer data.
+ *
+ * \param *events events struct
+ * \param *equalizer_levels pointer to 128 entries where equalizer
+ * is to be copied from.
+ *
+ * \return void
+ * \retval void
+ */
+void reload_equalizer(events_t *events, unsigned 4 *equalizer_levels) {
+ unsigned 7 equalizer_band;
+
+ events->locked_display = TRUE;
+ delay;
+ do {
+ events->equalizer_display[equalizer_band] = equalizer_table_inv[equalizer_levels[equalizer_band]];
+ equalizer_band++;
+ } while (equalizer_band);
+ events->locked_display = FALSE;
+} /* --- reload_equalizer() --- */