Skip to content

Instantly share code, notes, and snippets.

@Electronza
Last active May 2, 2020 13:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Electronza/0c3898b4d14900fd907f3bc5eed234ec to your computer and use it in GitHub Desktop.
Save Electronza/0c3898b4d14900fd907f3bc5eed234ec to your computer and use it in GitHub Desktop.
EasyPIC v7: Talking breathalizer
/*
* Project name:
Talking drunkometer (Demonstration of SmartMP3 board and Alcohol click)
* Description:
This project helps you get plastered
* Test configuration:
MCU: PIC18F45K22
http://ww1.microchip.com/downloads/en/DeviceDoc/41412D.pdf
Dev.Board: EasyPIC7
http://www.mikroe.com/easypic/
Oscillator: HS-PLL 32.0000 MHz, 8.0000 MHz Crystal
ext. modules: Smartmp3 boardmp3
http://www.mikroe.com/add-on-boards/audio-voice/smartmp3/
2x16 lcd character displaylcd
Alcohol click
http://www.mikroe.com/click/alcohol/
SW: mikroC PRO for PIC
http://www.mikroe.com/mikroc/pic/
* NOTES:
- External power supply is highly recommended
- Put power supply jumper (J5) on the EasyPIC7 board in the 5V position.
- Configure SmartMP3 board for 5V operation
- Put PORTA switches in the middle (neutral) position.
- Put PORTD switches in the pull-down position and put Button Press
Level jumper J17 in the VCC position.
- Use RD0 and RD2 to increase volume for left and right channels,
RD1 and RD3 do decrease volume for left and right channels, respectively.
- MP3 file should have the following name : "trackxx.mp3".
- Put Alcohol click into mikroBUS socket #1
*/
#include "SmartMP3_routines.h"
// Lcd module connections
sbit LCD_RS_Direction at TRISB4_bit;
sbit LCD_EN_Direction at TRISB5_bit;
sbit LCD_D4_Direction at TRISB0_bit;
sbit LCD_D5_Direction at TRISB1_bit;
sbit LCD_D6_Direction at TRISB2_bit;
sbit LCD_D7_Direction at TRISB3_bit;
sbit LCD_RS at LATB4_bit;
sbit LCD_EN at LATB5_bit;
sbit LCD_D4 at LATB0_bit;
sbit LCD_D5 at LATB1_bit;
sbit LCD_D6 at LATB2_bit;
sbit LCD_D7 at LATB3_bit;
// button to start measurement
sbit BTN at LATE0_bit;
sbit BTN_Direction at TRISE0_bit;
// Treshholds for messages
// change according to your sensor sensitivity
// and to position of potentiometer on Alcohol click
// (needs some experiments)
unsigned int sober = 20;
unsigned int tipsy = 80;
unsigned int drunk = 150;
// Some variables
unsigned int i; // used in for loops
int refr; // refecence value
int alcohol;
unsigned char disp[8];
void main() {
// Alcohol click is connected to RAd (analog)
ANSELA = 0x0C; // Set ADC on RA2
TRISA = 0x0C; // Set RA2 as input
ANSELB = 0; // Configure PORTB pins as digital
ANSELC = 0; // Configure PORTC pins as digital
ANSELD = 0; // Configure PORTD pins as digital
ANSELE = 0; // Configure PORTE pins as digital
SLRCON = 0; // Configure all PORTS at the standard Slew
BTN_Direction = 1; // RE0 as input
Lcd_Init(); // Initialize Lcd
MP3_Init();
// Setting the Alcohol click
ADC_Init(); // Initialize ADC
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
Lcd_Out(1,1,"Calibrate");
for (i = 0; i < 150; i++){
// start calibration
alcohol = ADC_Read(2); // Read RA2
refr = ADC_Read(3); // Read RA3
IntToStr ((alcohol-refr), disp);
Lcd_Out(2, 1, disp);
Delay_ms(100);
}
while(1){
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Out(1,1,"Press RE0");
while(Button(&PORTE, 0, 1, 1)){
// Wait for button press
}
Delay_ms(4000);
// RE2 pressed, start measuring
alcohol = ADC_Read(2); // Read RA2
refr = ADC_Read(3); // Read RA3
Lcd_Cmd(_LCD_CLEAR); // Clear display
if (alcohol < (refr + sober)){
Lcd_Out(1,1,"Start drinking");
MP3_Play("track01.mp3");
}
if ((alcohol >= (refr + sober)) & (alcohol < (refr + tipsy))){
Lcd_Out(1,1,"You need wine");
MP3_Play("track02.mp3");
}
if ((alcohol >= (refr + tipsy)) & (alcohol < (refr + drunk))){
Lcd_Out(1,1,"Drink water");
MP3_Play("track03.mp3");
}
if (alcohol >= (refr + drunk)){
Lcd_Out(1,1,"Go home!");
MP3_Play("track04.mp3");
}
}
}
#include <built_in.h>
// CODEC V1053E connections
sbit MP3_CS_Direction at TRISC1_bit;
sbit MP3_CS at LATC1_bit;
sbit MP3_RST_Direction at TRISC2_bit;
sbit MP3_RST at LATC2_bit;
sbit DREQ_Direction at TRISC7_bit;
sbit DREQ at RC7_bit;
sbit BSYNC_Direction at TRISC6_bit;
sbit BSYNC at LATC6_bit;
// MMC module connections
sbit Mmc_Chip_Select_Direction at TRISC0_bit;
sbit Mmc_Chip_Select at LATC0_bit; // for writing to output pin always use latch (PIC18 family)
// Buttons for Left/Right Volume control
sbit BtnLeftDown_Direction at TRISD3_bit;
sbit BtnLeftUp_Direction at TRISD2_bit;
sbit BtnRightDown_Direction at TRISD1_bit;
sbit BtnRightUp_Direction at TRISD0_bit;
sbit BtnLeftDown at RD3_bit;
sbit BtnLeftUp at RD2_bit;
sbit BtnRightDown at RD1_bit;
sbit BtnRightUp at RD0_bit;
// VS1053E constants
const char WRITE_CODE = 0x02;
const char READ_CODE = 0x03;
// Module constants
const char SCI_BASE_ADDR = 0x00;
const char SCI_MODE_ADDR = 0x00;
const char SCI_STATUS_ADDR = 0x01;
const char SCI_BASS_ADDR = 0x02;
const char SCI_CLOCKF_ADDR = 0x03;
const char SCI_DECODE_TIME_ADDR = 0x04;
const char SCI_AUDATA_ADDR = 0x05;
const char SCI_WRAM_ADDR = 0x06;
const char SCI_WRAMADDR_ADDR = 0x07;
const char SCI_HDAT0_ADDR = 0x08;
const char SCI_HDAT1_ADDR = 0x09;
const char SCI_AIADDR_ADDR = 0x0A;
const char SCI_VOL_ADDR = 0x0B;
const char SCI_AICTRL0_ADDR = 0x0C;
const char SCI_AICTRL1_ADDR = 0x0D;
const char SCI_AICTRL2_ADDR = 0x0E;
const char SCI_AICTRL3_ADDR = 0x0F;
// Global Variables
unsigned long file_size;
const BYTES_2_WRITE = 32;
const BUFFER_SIZE = 448;
char mp3_buffer[BUFFER_SIZE];
char volume_left, volume_right;
// Function writes one byte to MP3 SCI
void MP3_SCI_Write(char address, unsigned int data_in) {
BSYNC = 1;
MP3_CS = 0; // select MP3 SCI
SPI1_Write(WRITE_CODE);
SPI1_Write(address);
SPI1_Write(Hi(data_in)); // high byte
SPI1_Write(Lo(data_in)); // low byte
MP3_CS = 1; // deselect MP3 SCI
// wait until DREQ becomes 1, see MP3 codec datasheet, Serial Protocol for SCI
while (DREQ == 0)
;
}
// Function reads words_count words from MP3 SCI
void MP3_SCI_Read(char start_address, char words_count, unsigned int *data_buffer) {
unsigned int temp;
MP3_CS = 0; // select MP3 SCI
SPI1_Write(READ_CODE); // Enter into reading mode
SPI1_Write(start_address); // Start reading from the starting address
while (words_count) { // read words_count words byte per byte
words_count--;
temp = SPI1_Read(0);
temp = temp << 8;
temp = temp + SPI1_Read(0);
*data_buffer = temp;
data_buffer++;
}
MP3_CS = 1; // deselect MP3 SCI
// wait until DREQ becomes 1, see MP3 codec datasheet, Serial Protocol for SCI
while (DREQ == 0)
;
}
// Function write one byte to MP3 SDI
void MP3_SDI_Write(char data_) {
MP3_CS = 1; // deselect MP3 SCI
BSYNC = 0;
// wait until DREQ becomes 1, see MP3 codec datasheet, Serial Protocol for SCI
while (DREQ == 0)
;
SPI1_Write(data_); // write data to MP3 codec
BSYNC = 1;
}
// Function Write 32 bytes to MP3 SDI
void MP3_SDI_Write_32(char *data_) {
char i;
MP3_CS = 1;
BSYNC = 0;
// wait until DREQ becomes 1, see MP3 codec datasheet, Serial Protocol for SCI
while (DREQ == 0)
;
for (i=0; i<32; i++)
SPI1_Write(data_[i]);
BSYNC = 1;
}
// Function set volume on the left and right channel
void MP3_Set_Volume(char left, char right) {
unsigned int volume;
volume = (left<<8) + right; // calculate value
MP3_SCI_Write(SCI_VOL_ADDR, volume); // Write value to VOL register
}
// Function updates volume if volume Buttons are pressed
void MP3_Check_Volume() {
char old_volume_left, old_volume_right;
BtnLeftDown_Direction = 1; // set pin direction as input
BtnLeftUp_Direction = 1;
BtnRightDown_Direction = 1;
BtnRightUp_Direction = 1;
BtnLeftDown = 0; // set pin value to zero
BtnLeftUp = 0;
BtnRightDown = 0;
BtnRightUp = 0;
old_volume_left = volume_left; // save volume values
old_volume_right = volume_right;
if (BtnLeftDown) { // RD3 pressed = LEFT VOLUME DOWN command
if (volume_left < 255) {
volume_left++;
}
}
if (BtnLeftUp) { // RD2 pressed = LEFT VOLUME UP command
if (volume_left > 0) {
volume_left--;
}
}
if (BtnRightDown) { // RD1 pressed = RIGHT VOLUME DOWN command
if (volume_right < 255) {
volume_right++;
}
}
if (BtnRightUp) { // RD0 pressed = RIGHT VOLUME UP command
if (volume_right > 0) {
volume_right--;
}
}
// if volume values are changed, set volume to new values
if ( (volume_left != old_volume_left) || (volume_right != old_volume_right) ) {
MP3_Set_Volume(volume_left,volume_right);
}
}
// Function initializes MP3 codec
void MP3_Init() {
MP3_CS_Direction = 0; // Configure MP3_CS as output
MP3_CS = 1; // Deselect MP3_CS
MP3_RST_Direction = 0; // Configure MP3_RST as output
MP3_RST = 1; // Set MP3_RST pin
DREQ_Direction = 1; // Configure DREQ as input
BSYNC_Direction = 0; // Configure BSYNC as output
BSYNC = 0; // Clear BSYNC
// Initialize SPI1 module
SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV16, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH);
// Hardware reset
MP3_RST = 0;
Delay_ms(10);
MP3_RST = 1;
// wait until DREQ becomes 1, see MP3 codec datasheet, Serial Protocol for SCI
while (DREQ == 0)
;
MP3_SCI_Write(SCI_MODE_ADDR, 0x0800);
MP3_SCI_Write(SCI_BASS_ADDR, 0x7A00);
MP3_SCI_Write(SCI_CLOCKF_ADDR, 0xC000); // default 12 288 000 Hz + PLL
SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV4, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH);
Delay_ms(100);
// Maximum volume is 0x00 and total silence is 0xFE.
volume_left = 50; // Set volume to initial value
volume_right = 50;
MP3_Set_Volume(volume_left,volume_right);
Delay_ms(1000);
}
// Function plays mp3 file
// Instead of void MP3_Play() we will have
void MP3_Play(char filename[]) {
unsigned long i;
if (Mmc_Fat_Init() == 0) {
// I have commented out some of the LCD messages
// Lcd_Cmd(_LCD_CLEAR); // Clear display
// Lcd_Out(1,5,"MMC FAT");
// Lcd_Out(2,1,"initialized");
// Delay_ms(500);
// I have moved these lines to the main code
// Lcd_Cmd(_LCD_CLEAR); // Clear display
// Lcd_Out(1,1,"Playing file :");
// Lcd_Out(2,1,filename);
// The code line
// if (Mmc_Fat_Assign("sound.mp3", 0) )
// becomes
if (Mmc_Fat_Assign(filename, 0) ) {
// the rest of the code remains unchanged
// Lcd_Cmd(_LCD_CLEAR); // Clear display
///Lcd_Out(1,2,"File Assigned");
Delay_ms(100); // Shorter delay than in the code example
Mmc_Fat_Reset(&file_size); // Call Reset before file reading,
// procedure returns size of the file
// send file blocks to MP3 SDI
while (file_size > BUFFER_SIZE) {
// Set the SPI faster when reading data from mikro SD memory
SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV4, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH);
for (i=0; i<BUFFER_SIZE; i++) {
Mmc_Fat_Read(mp3_buffer + i);
}
// Set the SPI slower when sending data to mp3 codec
SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV16, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH);
for (i=0; i<BUFFER_SIZE/BYTES_2_WRITE; i++) {
MP3_SDI_Write_32(mp3_buffer + i*BYTES_2_WRITE);
}
file_size -= BUFFER_SIZE;
MP3_Check_Volume(); // Update volume
}
// send the rest of the file to MP3 SDI
// Set the SPI faster when reading data from mikro SD memory
SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV4, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH);
for (i=0; i<file_size; i++) {
Mmc_Fat_Read(mp3_buffer + i);
}
// Set the SPI slower when sending data to mp3 codec
SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV16, _SPI_DATA_SAMPLE_MIDDLE, _SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH);
for (i=0; i<file_size; i++) {
MP3_SDI_Write(mp3_buffer[i]);
}
// Display finishing message
// Lcd_Cmd(_LCD_CLEAR); // Clear display
// Lcd_Out(1,4,"Finished.");
Delay_ms(1500);
}
// Display error message
// Those messages remain as I want to know if something goes wrong
else {
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Out(1,1,"File not");
Lcd_Out(2,4,"assigned");
Delay_ms(1500);
}
}
// Display error message
else {
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Out(1,5,"MMC FAT");
Lcd_Out(2,1,"not initialized");
Delay_ms(1500);
}
}
// Module functions
void MP3_Init();
// To be able to pass filenames into the MP3 function we have to change
// void MP3_Play();
// to
void MP3_Play(char filename[]);
void MP3_SCI_Write(char address, unsigned int data_in);
void MP3_SCI_Read(char start_address, char words_count, unsigned int *data_buffer);
void MP3_SDI_Write(char data_);
void MP3_SDI_Write_32(char *data_);
void MP3_Set_Volume(char left, char right);
void MP3_Check_Volume();
# Project page
# dd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment