static void displaySMeter(int RSL) { int x = 80; int y = 68; LCD_SetDisplayWindow(x, y, SMETER_HEIGHT, FFT_WIDTH); LCD_WriteRAM_PrepareDir(LCD_WriteRAMDir_Down); int Signal_Level = ((RSL + 120) * 26) / 10; for (int x = 0; x < FFT_WIDTH; x++) { for (int y = 0; y < SMETER_HEIGHT; y++) { if (x <= Signal_Level) { LCD_WriteRAM(LCD_COLOR_GREEN); } else { LCD_WriteRAM(LCD_COLOR_DGRAY); } } } char SMeter$[7]; if (Signal_Level < 120) { if (Signal_Level < 0) Signal_Level = 0; int SLevel = Signal_Level / 12; sprintf(SMeter$, "S%i ", SLevel); } else { int SLevel = 9; int R = (Signal_Level - 100) / 3; sprintf(SMeter$, "S%i+%2i", SLevel, R); } GL_SetBackColor(LCD_COLOR_BLACK); GL_SetTextColor(LCD_COLOR_WHITE); GL_PrintString(1, 64, SMeter$, 0); }
static void WidgetFFT_DrawHandler(GL_PageControls_TypeDef* pThis, _Bool force) { // Bail if nothing to draw. if (!force && !DSP_Flag) { return; } int x = pThis->objCoordinates.MinX; int y = pThis->objCoordinates.MinY; /* * Calculate the data to draw: * - Use FFT_Magnitude[0..127] which is 0 to +4kHz of frequency * (don't use last half which is -4kHz to 0kHz) * - Scale the values up to fill a wider portion of the display. * (by averaging with neighboring data). This helps allow the * user to tap on frequencies to select them with better resolution. * - Average with "old" data from the previous pass to give it an * effective time-based smoothing (as in, display does not change * as abruptly as it would when using new data samples each time). */ //uint8_t FFT_Display[256]; static uint8_t FFT_Output[128]; // static because use last rounds data now. // TODO: Where are all these FFT constants from? for (int16_t j = 0; j < 128; j++) { // Changed for getting right display with SR6.3 // Convert from Q15 (fractional numeric representation) into integer FFT_Output[j] = (uint8_t) (6 * log((float32_t) (FFT_Magnitude[j] + 1))); if (FFT_Output[j] > 64) FFT_Output[j] = 64; FFT_Display[2 * j] = FFT_Output[j]; // Note that calculation uses values from last pass through. FFT_Display[2 * j + 1] = 0; //FFT_Display[2 * j + 1] = (FFT_Output[j] + FFT_Output[j + 1]) / 2; } /* * Display the FFT * - Drop the bottom 8, and top 8 frequency-display bins to discard * noisy sections near band edges due to filtering. */ float selectedFreqX = (float) (NCO_Frequency - 125) / 15.625; if (selectedFreqX < 0) { selectedFreqX = 0; } // Draw the FFT using direct memory writes (fast). LCD_SetDisplayWindow(x, y, FFT_HEIGHT, FFT_WIDTH); LCD_WriteRAM_PrepareDir(LCD_WriteRAMDir_Down); for (int x = 0; x < FFT_WIDTH; x++) { // Plot this column of the FFT. for (int y = 0; y < FFT_HEIGHT; y++) { // Draw red line for selected frequency if (x == (int) selectedFreqX) { // Leave some white at the top if (y <= SELFREQ_ADJ) { LCD_WriteRAM(LCD_COLOR_WHITE); } else { LCD_WriteRAM(LCD_COLOR_RED); } } // Draw data else if (FFT_HEIGHT - y < FFT_Display[x + 8]) { LCD_WriteRAM(LCD_COLOR_BLUE); } // Draw background else { LCD_WriteRAM(LCD_COLOR_WHITE); } } } // Update the frequency offset displayed (text): static double oldSelectedFreq = -1; if (force || oldSelectedFreq != NCO_Frequency) { oldSelectedFreq = NCO_Frequency; int textY = y + FFT_HEIGHT + TEXT_OFFSET_BELOW_FFT; int numberX = x + FFT_WIDTH - MAX_FREQ_DIGITS * CHARACTER_WIDTH; int labelX = numberX - CHARACTER_WIDTH * 8; // 7=# letters in label w/ a space GL_SetFont(GL_FONTOPTION_8x16); GL_SetBackColor(LCD_COLOR_BLACK); GL_SetTextColor(LCD_COLOR_WHITE); GL_PrintString(labelX, textY, "Offset:", 0); // Display location on label. GL_SetTextColor(LCD_COLOR_RED); char number[MAX_FREQ_DIGITS + 1]; intToCommaString((int)NCO_Frequency, number, MAX_FREQ_DIGITS + 1); GL_PrintString(numberX, textY, number, 0); } DSP_Flag = 0; // added per Charley }
static void displayFFT(int x, int y) { for (int16_t j = 0; j < 256; j++) { if (FFT_Filter[j] > 64.0) { FFT_Display[j] = 64; } else { FFT_Display[j] = (uint8_t)FFT_Filter[j]; } } /* * Display the FFT * - Drop the bottom 8, and top 8 frequency-display bins to discard * noisy sections near band edges due to filtering. */ float selectedFreqX = (float) (NCO_Frequency - 125) / 15.625; if (selectedFreqX < 0) { selectedFreqX = 0; } NCO_Bin = (int)selectedFreqX + 8; _Bool isShowingAFOffset = showAFOffsetOnScreen(); if (!WF_Flag) { // Draw the FFT using direct memory writes (fast). LCD_SetDisplayWindow(x, y, FFT_HEIGHT, FFT_WIDTH); LCD_WriteRAM_PrepareDir(LCD_WriteRAMDir_Down); for (int x = 0; x < FFT_WIDTH; x++) { // Plot this column of the FFT. for (int y = 0; y < FFT_HEIGHT; y++) { // Draw red line for selected frequency if ((x == (int) (selectedFreqX + 0.5)) && isShowingAFOffset) { // Leave some white at the top if (y <= SELFREQ_ADJ) { LCD_WriteRAM(LCD_COLOR_WHITE); } else { LCD_WriteRAM(LCD_COLOR_RED); } } // Draw data else if (FFT_HEIGHT - y < FFT_Display[x + 8]) { LCD_WriteRAM(LCD_COLOR_BLUE); } // Draw background else { LCD_WriteRAM(LCD_COLOR_WHITE); } } } } else { if (WF_Count == 0) { // Draw the Waterfall using direct memory writes (fast). LCD_SetDisplayWindow(x, y, FFT_HEIGHT, FFT_WIDTH); LCD_WriteRAM_PrepareDir(LCD_WriteRAMDir_Right); // Send colorized FFT data to Waterfall Buffer for (int x = 0; x < FFT_WIDTH; x++) { *(pWFBfr + (FFT_WIDTH*WF_Line0) + x) = WFPalette[(FFT_Display[x + 8] )]; } // Refresh the waterfall display--scrolling begins after 64 lines for (int y = WF_Line0; y < FFT_HEIGHT; y++) { for (int x = 0; x <FFT_WIDTH; x++) { if (x == (int)(selectedFreqX +0.5) && isShowingAFOffset) { //LCD_WriteRAM(LCD_COLOR_RED); LCD_WriteRAM(LCD_COLOR_WHITE); } else { LCD_WriteRAM(*(pWFBfr + y*FFT_WIDTH + x)); } } } for ( int y = 0; y < WF_Line0; y++) { for (int x = 0; x < FFT_WIDTH; x++) { if (x == (int)(selectedFreqX +0.5) && isShowingAFOffset) { //LCD_WriteRAM(LCD_COLOR_RED); LCD_WriteRAM(LCD_COLOR_WHITE); } else { LCD_WriteRAM(*(pWFBfr + y*FFT_WIDTH + x)); } } } } if (++WF_Count == MAX_WF_COUNT) { WF_Count = 0; WF_Line0--; if (WF_Line0 < 0) WF_Line0 = FFT_HEIGHT-1; } } }