/** @file
Logo DXE Driver, install Edkii Platform Logo protocol.
Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/ShellCEntryLib.h>
#include <Protocol/HiiDatabase.h>
#include <Protocol/GraphicsOutput.h>
#include <Protocol/HiiImageEx.h>
#include <Protocol/PlatformLogo.h>
#include <Protocol/HiiPackageList.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/DebugLib.h>
#include <Library/PrintLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/BaseLib.h>
#include <Library/UefiApplicationEntryPoint.h>
#include <Library/ShellLib.h>
#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \
{ \
0x9042a9de, 0x23dc, 0x4a38, {0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a } \
}
static EFI_GUID GraphicsOutputProtocolGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
//DO NOT REMOVE IMAGE_TOKEN (IMG_LOGO)
/**
Entrypoint of this module.
This function is the entrypoint of this module. It installs the Edkii
Platform Logo protocol.
@param ImageHandle The firmware allocated handle for the EFI image.
@param SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The entry point is executed successfully.
**/
EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
EFI_STATUS Status;
EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;
EFI_HII_IMAGE_PACKAGE_HDR *ImageHeader;
UINT8 *ImageData;
UINTN FileSize;
EFI_FILE_HANDLE FileHandle;
//Step1. Get Package List Header Address
//
// Retrieve HII package list from ImageHandle
//
Status = gBS->OpenProtocol (
ImageHandle,
&gEfiHiiPackageListProtocolGuid,
(VOID **) &PackageListHeader,
ImageHandle,
NULL,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
Print(L"HII Image Package with logo not found in PE/COFF resource section\n");
return Status;
}
Print(L"PackageList :\nGUID=[%g] Length=[%X]\n",
PackageListHeader->PackageListGuid,
PackageListHeader->PackageLength);
//Step2. Parser HII Image
ImageHeader=(EFI_HII_IMAGE_PACKAGE_HDR*)(PackageListHeader+1);
ImageData=(UINT8 *)(ImageHeader+1);
FileSize=ImageData[1]+(ImageData[2]<<8)+(ImageData[3]<<16)+(ImageData[4]<<24);
Print(L"Type: 0x%x Size:%d\n",ImageData[0],FileSize);
//Create a new file
Status = ShellOpenFileByName(L"dump.bin",
(SHELL_FILE_HANDLE *)&FileHandle,
EFI_FILE_MODE_READ |
EFI_FILE_MODE_WRITE|
EFI_FILE_MODE_CREATE,
0);
if(Status != RETURN_SUCCESS) {
Print(L"CreatFile failed [%r]!\n",Status);
return EFI_SUCCESS;
}
Status = ShellWriteFile(FileHandle,
&FileSize,
&ImageData[5]);
//Close the source file
ShellCloseFile(&FileHandle);
Print(L"Dump.bin is generated!\n");
return Status;
}
typedef WINBASEAPI BOOL (WINAPI *ImmDisableIMEProc) (DWORD unnamedParam1);
typedef WINBASEAPI HIMC (WINAPI *ImmAssociateContextProc) (HWND unnamedParam1, HIMC unnamedParam2);
/**
This thread simulates the end of WinMain () application. Each Window needs
to process its events. The messages are dispatched to
WinNtGopThreadWindowProc ().
Be very careful since WinNtGopThreadWinMain () and WinNtGopThreadWindowProc ()
are running in a separate thread. We have to do this to process the events.
@param lpParameter Handle of window to manage.
@return if a WM_QUIT message is returned exit.
**/
DWORD
WINAPI
WinNtGopThreadWinMain (
LPVOID lpParameter
)
{
MSG Message;
GRAPHICS_PRIVATE_DATA *Private;
RECT Rect;
//LABZ_Debug_Start
HMODULE Module;
ImmDisableIMEProc ImmDisable;
Module = LoadLibraryEx (L"imm32.dll", NULL, DONT_RESOLVE_DLL_REFERENCES);
ImmDisable = (ImmDisableIMEProc)GetProcAddress(Module, "ImmDisableIME");
if (ImmDisable)
ImmDisable(GetCurrentThreadId ());
//LABZ_Debug_End
Private = (GRAPHICS_PRIVATE_DATA *)lpParameter;
ASSERT (NULL != Private);
#include <arduinoFFT.h>
#include "DFRobot_OLED12864.h"
// 12864 OLED 配置
#define I2C_addr 0x3c
#define pin_SPI_cs D2
#define SAMPLES 1024 // Must be a power of 2
#define SAMPLING_FREQ 40000 // Hz, must be 40000 or less due to ADC conversion time. Determines maximum frequency that can be analysed by the FFT Fmax=sampleF/2.
#define AMPLITUDE 1000 // Depending on your audio source level, you may need to alter this value. Can be used as a 'sensitivity' control.
#define AUDIO_IN_PIN A0 // Signal in on this pin
#define NOISE 500 // Used as a crude noise filter, values below this are ignored
const uint8_t kMatrixWidth = 16; // Matrix width
const uint8_t kMatrixHeight = 16; // Matrix height
#define NUM_BANDS 16 // To change this, you will need to change the bunch of if statements describing the mapping from bins to bands
#define BAR_WIDTH (kMatrixWidth / (NUM_BANDS - 1)) // If width >= 8 light 1 LED width per bar, >= 16 light 2 LEDs width bar etc
#define TOP (kMatrixHeight - 0) // Don't allow the bars to go offscreen
DFRobot_OLED12864 OLED(I2C_addr, pin_SPI_cs);
// Sampling and FFT stuff
unsigned int sampling_period_us;
byte peak[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // The length of these arrays must be >= NUM_BANDS
int oldBarHeights[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int bandValues[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
double vReal[SAMPLES];
double vImag[SAMPLES];
unsigned long newTime;
arduinoFFT FFT = arduinoFFT(vReal, vImag, SAMPLES, SAMPLING_FREQ);
void setup() {
Serial.begin(115200);
OLED.init();
// OLED.flipScreenVertically();
sampling_period_us = round(1000000 * (1.0 / SAMPLING_FREQ));
}
unsigned long int Elsp1;
int h[16];
void loop() {
// Reset bandValues[]
for (int i = 0; i < NUM_BANDS; i++) {
bandValues[i] = 0;
}
// Sample the audio pin
for (int i = 0; i < SAMPLES; i++) {
newTime = micros();
vReal[i] = analogRead(AUDIO_IN_PIN); // A conversion takes about 9.7uS on an ESP32
vImag[i] = 0;
while ((micros() - newTime) < sampling_period_us) {
/* chill */
}
}
// Compute FFT
FFT.DCRemoval();
FFT.Windowing(FFT_WIN_TYP_HAMMING, FFT_FORWARD);
FFT.Compute(FFT_FORWARD);
FFT.ComplexToMagnitude();
// Analyse FFT results
for (int i = 2; i < (SAMPLES / 2); i++) { // Don't use sample 0 and only first SAMPLES/2 are usable. Each array element represents a frequency bin and its value the amplitude.
if (vReal[i] > NOISE) { // Add a crude noise filter
//16 bands, 12kHz top band
if (i <= 2 ) bandValues[0] += (int)vReal[i];
if (i > 2 && i <= 3 ) bandValues[1] += (int)vReal[i];
if (i > 3 && i <= 5 ) bandValues[2] += (int)vReal[i];
if (i > 5 && i <= 7 ) bandValues[3] += (int)vReal[i];
if (i > 7 && i <= 9 ) bandValues[4] += (int)vReal[i];
if (i > 9 && i <= 13 ) bandValues[5] += (int)vReal[i];
if (i > 13 && i <= 18 ) bandValues[6] += (int)vReal[i];
if (i > 18 && i <= 25 ) bandValues[7] += (int)vReal[i];
if (i > 25 && i <= 36 ) bandValues[8] += (int)vReal[i];
if (i > 36 && i <= 50 ) bandValues[9] += (int)vReal[i];
if (i > 50 && i <= 69 ) bandValues[10] += (int)vReal[i];
if (i > 69 && i <= 97 ) bandValues[11] += (int)vReal[i];
if (i > 97 && i <= 135) bandValues[12] += (int)vReal[i];
if (i > 135 && i <= 189) bandValues[13] += (int)vReal[i];
if (i > 189 && i <= 264) bandValues[14] += (int)vReal[i];
if (i > 264 ) bandValues[15] += (int)vReal[i];
}
}
// Process the FFT data into bar heights
for (byte band = 0; band < NUM_BANDS; band++) {
// Scale the bars for the display
int barHeight = bandValues[band] / AMPLITUDE;
if (barHeight > TOP) barHeight = TOP;
// Small amount of averaging between frames
barHeight = ((oldBarHeights[band] * 1) + barHeight) / 2;
// Move peak up
if (barHeight > peak[band]) {
peak[band] = min(TOP, barHeight);
}
h[band] = barHeight;
// Save oldBarHeights for averaging later
oldBarHeights[band] = barHeight;
}
if (millis() - Elsp1 > 60) {
for (byte band = 0; band < NUM_BANDS; band++)
if (peak[band] > 0) peak[band] -= 1;
Elsp1 = millis();
}
/*
//直接输出 FFT 结果
for (int i=0;i<16;i++) {
if (bandValues[i]<16) {Serial.print(" ");}
Serial.print(bandValues[i],HEX);
Serial.print(" ");
}
Serial.println("");
*/
// 擦除上一次
OLED.clear();
for (int i = 0; i < 16; i++) {
OLED.fillRect(8 * (16-i), 0, 8, 4 * h[i]);
OLED.fillRect(8 * (16-i), peak[i]*4, 8, 3);
}
for (int i = 0; i < 16; i++) {
Serial.print(h[i], HEX);
Serial.print("");
}
Serial.println("");
/*
for (int i = 0; i < 16; i++) {
Serial.print(peak[i], HEX);
Serial.print("");
}
Serial.println("");
*/
// 显示当前
OLED.display();
}