NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » xylophone program

August 20, 2011
by quickpenn
quickpenn's Avatar

below is the program i downloaded from nerkits. i only changed the location of (#include "L:Semester 8CapstoneCodelibnerdkitsdelay.h") and (#include "L:Semester 8CapstoneCodelibnerdkitsuart.h") because compiler wouldn't find it other wise. i'm now getting the following errors and i need to know how to fix them.

Error 1 undefined reference to shiftregister_push' line 40 Error 2 undefined reference toshiftregister_push' line 51 Error 3 undefined reference to shiftregister_push' line 107 Error 4 undefined reference toshiftregister_push' line 114 Error 5 undefined reference to uart_init' line 579 Error 6 undefined reference touart_putchar' line 580 Error 7 undefined reference to uart_putchar' line 580 Error 8 undefined reference touart_getchar' line 580 Error 9 undefined reference to uart_getchar' line 580 Error 10 undefined reference todelay_ms' line 606 Error 11 undefined reference to delay_ms' line 608 Error 12 undefined reference todelay_ms' line 610 Error 13 undefined reference to delay_ms' line 612 Error 14 undefined reference todelay_ms' line 616

// xylophone.c
// for NerdKits with ATmega168
// mike @ nerdkits.com

#define F_CPU 14745600

#include <stdio.h>

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/sleep.h>
#include <inttypes.h>

#include "L:\Semester 8\Capstone\Code\libnerdkits\delay.h"
#include "L:\Semester 8\Capstone\Code\libnerdkits\uart.h"

// PIN DEFINITIONS:
//
// PB5 - SCK out (CLK to shift register)
// PB3 - MISO out (serial DATA to shift register)
// PB2 - SS out (just hold output to keep SPI module behaving properly)

inline void shiftregister_push(uint8_t data) {
  SPDR = data;
}

void shiftregister_init() {
  // SCK, MOSI, SS outputs
  DDRB |= (1<<PB5) | (1<<PB3) | (1<<PB2);

  // SPI setup
  // Master mode  
  // MSB first (DORD=0)
  // SPI2X = CK/2 (super-speed!)
  SPCR = (1<<SPE) | (1<<MSTR);
  SPSR = (1<<SPI2X);

  // shift out a zero to get started
  shiftregister_push(0);
}

void clear_time() {
  cli();
  // clear the count
  TCNT1 = 0;
  // clear interrupt flags
  TIFR1 |= (1<<OCF1B);
  TIFR1 |= (1<<OCF1A);
  // clear shift register
  shiftregister_push(0x00);
  sei();
}

void set_beat(uint16_t bpm) {
  // input in Beats Per Minute (60 .. ?)
  // set OCR1A appropriately.
  // 60 bpm -> 57600-1

  // (60/bpm)*(14745600/256) - 1
  // (60*14745600)/bpm/256 - 1
  // 3456000/bpm - 1
  // 
  uint32_t t = 3456000L;
  t = t / bpm;
  t = t - 1;
  if(t > 65536) {
    OCR1A = 65535;
  } else if(t < 2300) { // 20ms
    OCR1A = 2300;
  } else {
    OCR1A = (uint16_t) t;
  }
}

void metronome_init() {
  // setup Timer1 for Fast PWM mode, 16-bit
  // WGM12 -- for CTC with OCR1A as TOP value
  // CS12 -- for CLK/256 prescaling
  //
  // CLK/256:
  // 65536 = 1137.7 ms
  // 57600 = 1000.0 ms (60 bpm)
  // 28800 = 500.0 ms (120 bpm)
  // 19200 = 333.3 ms (180 bpm)
  // 14400 = 250.0 ms (240 bpm)
  // 346 = 6.0 ms
  // 288 = 5.0 ms
  // 230 = 4.0 ms

  OCR1A = 14400 - 1;    // set 240bpm initially
 //OCR1B = 346 - 1; // set 6ms on-time initially
 //OCR1B = 576 - 1; // set 10ms on-time initially
  OCR1B = 460 - 1;  // set 8ms on-time initially

  TCCR1A = 0;
  TCCR1B = (1<<WGM12) | (1<<CS12);

  // enable interrupts on CompareMatch B, CompareMatch A
  TIMSK1 = (1<<OCIE1B) | (1<<OCIE1A);
}

volatile uint8_t next_note = 0;
volatile uint8_t next_note_request = 0; // this becomes 1 when the interrupt handler is ready for the 
next note
ISR(TIMER1_COMPA_vect) {
  // this is the CTC event
  shiftregister_push(next_note);
  next_note = 0; // just in case we don't hear back
  next_note_request = 1;
}

ISR(TIMER1_COMPB_vect) {
  // this is the end of the mallet strike
  shiftregister_push(0x00);
}

__attribute__ ((noinline)) void play_note(uint8_t note) {
  // play it
  cli();
  next_note_request = 0;
  next_note = note;
  sei();
  //printf_P(PSTR("play_note: %d\r\n"), note);
  // wait for it to be played
  while(next_note_request == 0) {
    sleep_mode();
  }
}

#define NOTE_C6 (1<<0)
#define NOTE_D6 (1<<1)
#define NOTE_E6 (1<<2)
#define NOTE_F6 (1<<3)
#define NOTE_G6 (1<<4)
#define NOTE_A6 (1<<5)
#define NOTE_B6 (1<<6)
#define NOTE_C7 (1<<7)

void play_note_16(uint8_t note){
  play_note(note);
}

void play_note_8(uint8_t note){
  play_note(note);
  play_note(0);
}

void play_note_4(uint8_t note){
  play_note(note);
  uint8_t i;
  for(i=0;i<3;i++){
    play_note(0);
  }
}

void play_note_4_dot(uint8_t note){
  play_note(note);
  uint8_t i;
  for(i=0;i<6;i++){
    play_note(0);
  }
}

void play_note_2(uint8_t note){
  play_note(note);
  uint8_t i;
  for(i=0;i<7;i++){
    play_note(0);
  }
}

void play_note_2_dot(uint8_t note){
  play_note(note);
  uint8_t i;
  for(i=0;i<10;i++){
    play_note(0);
  }
}

void play_note_1(uint8_t note){
  play_note(note);
  uint8_t i;
  for(i=0;i<15;i++){
    play_note(0);
  }
}

void play_rest_4(){
  uint8_t i;
  for(i=0;i<4;i++){
    play_note(0);
  }
}

//duration in 16th notes
void play_trill(uint8_t note,uint8_t duration){
  uint8_t i;
  for(i=0;i<duration;i++){
    play_note_16(note);
  }
}

void song_cmajorscale_slow() {
  clear_time();
  set_beat(240);
  play_note(NOTE_C6);
  play_note(NOTE_D6);
  play_note(NOTE_E6);
  play_note(NOTE_F6);
  play_note(NOTE_G6);
  play_note(NOTE_A6);
  play_note(NOTE_B6);
  play_note(NOTE_C7);
  play_note(NOTE_B6);
  play_note(NOTE_A6);
  play_note(NOTE_G6);
  play_note(NOTE_F6);
  play_note(NOTE_E6);
  play_note(NOTE_D6);
  play_note(NOTE_C6);
}

void song_cmajorscale_fast() {
  clear_time();
  set_beat(960);
  play_note(NOTE_C6);
  play_note(NOTE_D6);
  play_note(NOTE_E6);
  play_note(NOTE_F6);
  play_note(NOTE_G6);
  play_note(NOTE_A6);
  play_note(NOTE_B6);
  play_note(NOTE_C7);
  play_note(NOTE_B6);
  play_note(NOTE_A6);
  play_note(NOTE_G6);
  play_note(NOTE_F6);
  play_note(NOTE_E6);
  play_note(NOTE_D6);
  play_note(NOTE_C6);
}

void song_twinkletwinkle() {
  clear_time();
  set_beat(240);
  play_note(NOTE_C6);
  play_note(NOTE_C6);
  play_note(NOTE_G6);
  play_note(NOTE_G6);

  play_note(NOTE_A6);
  play_note(NOTE_A6);
  play_note(NOTE_G6);
  play_note(0);

  play_note(NOTE_F6);
  play_note(NOTE_F6);
  play_note(NOTE_E6);
  play_note(NOTE_E6);

  play_note(NOTE_D6);
  play_note(NOTE_D6);
  play_note(NOTE_C6);
  play_note(0);

  play_note(NOTE_G6);
  play_note(NOTE_G6);
  play_note(NOTE_F6);
  play_note(NOTE_F6);

  play_note(NOTE_E6);
  play_note(NOTE_E6);
  play_note(NOTE_D6);
  play_note(0);

  play_note(NOTE_G6);
  play_note(NOTE_G6);
  play_note(NOTE_F6);
  play_note(NOTE_F6);

  play_note(NOTE_E6);
  play_note(NOTE_E6);
  play_note(NOTE_D6);
  play_note(0);

  play_note(NOTE_C6);
  play_note(NOTE_C6);
  play_note(NOTE_G6);
  play_note(NOTE_G6);

  play_note(NOTE_A6);
  play_note(NOTE_A6);
  play_note(NOTE_G6);
  play_note(0);

  play_note(NOTE_F6);
  play_note(NOTE_F6);
  play_note(NOTE_E6);
  play_note(NOTE_E6);

  play_note(NOTE_D6);
  play_note(NOTE_D6);
  play_note(NOTE_C6);
  play_note(0);
}

void song_jinglebells() {
  clear_time();
  set_beat(180);

  uint8_t iter = 0;
  while(iter < 2) {
    play_note(NOTE_E6);
    play_note(NOTE_E6);
    play_note(NOTE_E6);
    play_note(0);

    play_note(NOTE_E6);
    play_note(NOTE_E6);
    play_note(NOTE_E6);
    play_note(0);

    play_note(NOTE_E6);
    play_note(NOTE_G6);
    play_note(NOTE_C6);
    play_note(NOTE_D6);

    play_note(NOTE_E6);
    play_note(0);
    play_note(0);
    play_note(0);

    play_note(NOTE_F6);
    play_note(NOTE_F6);
    play_note(NOTE_F6);
    play_note(0);
    set_beat(360);
    play_note(NOTE_F6);

    if(iter==0) {
      // ending 1
      play_note(NOTE_F6);
      set_beat(180);
      play_note(NOTE_E6);
      play_note(NOTE_E6);
      play_note(0);
      set_beat(360);
      play_note(NOTE_E6);

      play_note(NOTE_E6);
      set_beat(180);
      play_note(NOTE_D6);
      play_note(NOTE_D6);
      play_note(NOTE_E6);

      play_note(NOTE_D6);
      play_note(0);
      play_note(NOTE_G6);
      play_note(0);

    } else {
      // ending 2
      play_note(NOTE_F6);
      set_beat(180);
      play_note(NOTE_E6);
      play_note(NOTE_E6);
      play_note(NOTE_E6);
      set_beat(360);
      play_note(NOTE_E6);

      play_note(NOTE_G6);
      set_beat(180);
      play_note(NOTE_G6);
      play_note(NOTE_F6);    
      play_note(NOTE_D6);

      play_note(NOTE_C6);
      play_note(0);
      play_note(0);
      play_note(0);  
    }
    iter++;
  }
}

void song_joy(){
  clear_time();
  set_beat(260*4);

  play_note_2(NOTE_C7 | NOTE_E6);
  play_note_4_dot(NOTE_B6 | NOTE_F6);
  play_note_8(NOTE_A6);

  play_note_2_dot(NOTE_G6 | NOTE_E6);
  play_note_4(NOTE_F6);

  play_note_2(NOTE_E6);
  play_note_2(NOTE_D6);

  play_note_2_dot(NOTE_C6);
  play_note_4(NOTE_G6);

  play_note_2_dot(NOTE_A6 | NOTE_F6);
  play_note_4(NOTE_A6);

  play_note_2_dot(NOTE_B6 | NOTE_F6);
  play_note_4(NOTE_B6);

  //play_note_1(NOTE_C7 | NOTE_E6);
  //play_note_2_dot(0);
  play_trill(NOTE_C7,24);

  play_note_4(0);
  play_note_4(NOTE_C7);

  play_note_4(NOTE_C7);
  play_note_4(NOTE_B6);
  play_note_4(NOTE_A6);
  play_note_4(NOTE_G6);

  play_note_4_dot(NOTE_G6);
  play_note_8(NOTE_F6);
  play_note_4(NOTE_E6);
  play_note_4(NOTE_C7);

  play_note_4(NOTE_C7);
  play_note_4(NOTE_B6);
  play_note_4(NOTE_A6);
  play_note_4(NOTE_G6);

  play_note_4_dot(NOTE_G6);
  play_note_8(NOTE_F6);
  play_note_4(NOTE_E6);
  play_note_4(NOTE_E6);

  play_note_4(NOTE_E6);
  play_note_4(NOTE_E6);
  play_note_4(NOTE_E6);
  play_note_8(NOTE_E6);
  play_note_8(NOTE_F6);

  play_note_2_dot(NOTE_G6 | NOTE_E6);
  play_note_8(NOTE_F6);
  play_note_8(NOTE_E6);

  play_note_4(NOTE_D6);
  play_note_4(NOTE_D6);
  play_note_4(NOTE_D6);
  play_note_8(NOTE_D6);
  play_note_8(NOTE_E6);

  play_note_2_dot(NOTE_F6 | NOTE_D6);
  play_note_8(NOTE_E6);
  play_note_8(NOTE_D6);

  play_note_4(NOTE_C6);
  play_note_2(NOTE_C7);
  play_note_4(NOTE_A6);

  play_note_4_dot(NOTE_G6);
  play_note_8(NOTE_F6);
  play_note_4(NOTE_E6);
  play_note_4(NOTE_F6);

  play_note_2(NOTE_E6);
  play_note_2(NOTE_D6);

  play_note_1(NOTE_C6);

}

void song_jolly_good(){
  clear_time();
  set_beat(640*4);

  play_note_4_dot(NOTE_G6);

  play_note_2(NOTE_E6 | NOTE_C6);
  play_note_4(NOTE_E6);

  play_note_4(NOTE_E6);
  play_note_4(NOTE_D6);
  play_note_4(NOTE_E6);

  play_note_2_dot(NOTE_F6 | NOTE_C6);

  play_note_2(NOTE_E6 | NOTE_C6);
  play_note_4(NOTE_E6);

  play_note_2(NOTE_D6);
  play_note_4(NOTE_D6);

  play_note_4(NOTE_D6);
  play_note_4(NOTE_C6);
  play_note_4(NOTE_D6);

  play_note_2_dot(NOTE_E6 | NOTE_C6);
//8
  play_note_2(NOTE_C6);
  play_note_4(NOTE_C6);

  play_note_2(NOTE_E6);
  play_note_4(NOTE_E6);

  play_note_4(NOTE_E6);
  play_note_4(NOTE_D6);
  play_note_4(NOTE_E6);

  play_note_2(NOTE_F6 | NOTE_C6);
  play_note_4(NOTE_G6);

  play_trill(NOTE_A6 | NOTE_F6,12);
  play_note_4(0);

  play_note_4(NOTE_A6);

  play_note_4(NOTE_G6 | NOTE_C6);
  play_note_4(NOTE_G6);
  play_note_4(NOTE_G6);

  play_note_2(NOTE_F6 | NOTE_C6);
  play_note_4(NOTE_D6);

  play_trill(NOTE_C6,12);
  play_note_2(0);
  play_note_4(0);

}

void song_intervals(){

  clear_time();
  uint16_t interval_beat = 400;
  uint8_t i;
  for(i=0;i<3;i++){
    play_note_16(NOTE_C6);
    set_beat(interval_beat);
    play_note_16(NOTE_E6);
    play_note_16(NOTE_D6);
    play_note_16(NOTE_F6);
    play_note_16(NOTE_E6);
    play_note_16(NOTE_G6);
    play_note_16(NOTE_F6);
    play_note_16(NOTE_A6);
    play_note_16(NOTE_G6);
    play_note_16(NOTE_B6);
    play_note_16(NOTE_A6);
    play_note_16(NOTE_C7);
    play_note_16(NOTE_B6);

    play_note_4(0);

    play_note_16(NOTE_C7);
    play_note_16(NOTE_A6);
    play_note_16(NOTE_B6);
    play_note_16(NOTE_G6);
    play_note_16(NOTE_A6);
    play_note_16(NOTE_F6);
    play_note_16(NOTE_G6);
    play_note_16(NOTE_E6);
    play_note_16(NOTE_F6);
    play_note_16(NOTE_D6);
    play_note_16(NOTE_E6);
    play_note_16(NOTE_C6);
    play_note_16(NOTE_E6);
    play_note_16(NOTE_E6); 
    play_note_16(NOTE_C6 | NOTE_E6 | NOTE_G6 | NOTE_C7);
    play_note_4(0);

    interval_beat += 100;
  }

}

int main() {
  // init serial port
  uart_init();
  FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);
  stdin = stdout = &uart_stream;

  // power reduction
  // disable TWI, Timer2, Timer0, ADC
  PRR = (1<<PRTWI) | (1<<PRTIM2) | (1<<PRTIM0) | (1<<PRADC);
  // select Idle sleep mode
  SMCR = 0;

  // set PB2 as output
  DDRB |= (1<<PB2);

  // init Timer
  metronome_init();

  // init shift register
  shiftregister_init();

  // enable global interrupts
  sei();

  printf_P(PSTR("Hello, world!\r\n"));

  while(1) {
    printf_P(PSTR("Playing song 2...\r\n"));
    song_cmajorscale_fast();
    delay_ms(1000);  
    song_cmajorscale_fast();  
    delay_ms(1000);
    song_cmajorscale_fast();
    delay_ms(1000);  
    song_cmajorscale_fast();
    delay_ms(1000);

    printf_P(PSTR("Playing intervals...\r\n"));
    song_intervals();
    delay_ms(1000);

    printf_P(PSTR("Playing For He's a Jolly Good Fellow...\r\n"));
    song_jolly_good();
    delay_ms(1000);

    printf_P(PSTR("Playing Jingle Bells...\r\n"));
    song_jinglebells();
    delay_ms(1000);

    printf_P(PSTR("Playing Joy To The World...\r\n"));
    song_joy();
    delay_ms(1000);

/*
    printf_P(PSTR("Playing song 1...\r\n"));
    song_cmajorscale_slow();
    delay_ms(1000);

    printf_P(PSTR("Playing song 2...\r\n"));
    song_cmajorscale_fast();
    delay_ms(1000);

    printf_P(PSTR("Playing song 3...\r\n"));
    song_twinkletwinkle();
    delay_ms(1000);

    printf_P(PSTR("Playing song 4...\r\n"));
    song_jinglebells();
    delay_ms(1000);
*/
  }

  return 0;
}

Post a Reply

Please log in to post a reply.

Did you know that Pulse Width Modulation (PWM) can be used to control the speed of a motor digitally? Learn more...