from machine import Pin, SPI import time, sdcard, os import network, socket class VS1053: def __init__(self, spi, cs, dcs, dreq, reset): self.cs = cs self.dcs = dcs self.dreq = dreq self.reset = reset self.spi = spi def init(self): self.cs.init(Pin.OUT, value=1) self.dcs.init(Pin.OUT, value=1) self.dreq.init(Pin.IN) self.reset.init(Pin.OUT, value=1) # Reset the VS1053 module self.reset(vs1053_reset) self.write_command(0x0, 0x8, 0x4) self.write_command(0x3, 0xe0, 0) # Clock multiplier self.write_command(0xb, 0x30, 0x30) # Volume control, 0-loudest for i in range(0,16,1): # For debug purpose, can be deleted print(self.read_register(i)) def reset(self,pin_reset): pin_reset.value(0) time.sleep_ms(1) pin_reset.value(1) def write_command(self, address_byte, data_byte1, data_byte2): # Set the control pins to indicate a command self.cs.value(0) while not self.dreq.value(): pass # Send the address and data bytes over SPI ba = (bytearray([0x02, address_byte, data_byte1, data_byte2])) self.spi.write(ba) # Turn off CS signals self.cs.value(1) def read_register(self, address_byte): # Set the control pins to indicate a command self.cs.value(0) while not self.dreq.value(): pass self.spi.write(bytearray([0x03, address_byte])) resp = self.spi.read(2) # Set the control pins to indicate data self.cs.value(1) return resp def write_data(self, data): # Set the control pins to indicate data self.dcs.value(0) # Wait for the data request pin to go high while not self.dreq.value(): pass self.spi.write(data) self.dcs.value(1) def play_file(self, filename): # Open the file and read the data chunk = 8192 with open(filename, "rb") as f: data = f.read(chunk) # Loop through the file and send the data to the VS1053 while data: idx = 0 while True: if idx+32 > len(data): self.write_data(data[idx:]) break else: self.write_data(data[idx:idx+32]) idx += 32 data = f.read(chunk) def play_stream(self,socket): while True: soundpacket = socket.recv(32) if soundpacket: self.write_data(soundpacket) else: break socket.close() class netradio: def connect_wifi(self,ssid,password): self.sta_if = network.WLAN(network.STA_IF) self.sta_if.active(True) self.sta_if.connect(ssid,password) while not self.sta_if.isconnected(): time.sleep_ms(500) def connect(self,radioURL): (radioIP,tcpPort,radioPath) = self.parseURL(radioURL) self.sock = socket.socket() addr = socket.getaddrinfo(radioIP, tcpPort)[0][-1] self.sock.connect(addr) request = "GET %s HTTP/1.0\r\nHost: %s\r\n\r\n" % (radioPath,radioIP) self.sock.send(request) return self.sock def parseURL(self,url): (proto,_,radioName,radioPath) = url.split("/",3) # Check for port number in radioName l = radioName.split(":") radioIP = l[0] if len(l)==1: tcpPort = 80 else: tcpPort = int(l[1]) return (radioIP,tcpPort,"/"+radioPath) def read_data(self,numbytes): return sock.recv(numbytes) # Define the pins for SPI communication spi_mosi = Pin(3) spi_miso = Pin(4) spi_sck = Pin(2) # Define the pins for the VS1053 module vs1053_cs = Pin(6) vs1053_dcs = Pin(7) vs1053_dreq = Pin(8) vs1053_reset = Pin(0) # Chip select for SD card reader sd_cs = Pin(1, Pin.OUT, value=1) # Initialize the SPI bus for the mp3 decoder and the sd card reader co_spi = SPI(0, baudrate=1000000, polarity=0, phase=0, sck=spi_sck, mosi=spi_mosi, miso=spi_miso) sd_spi = SPI(0) # Init SD card reader interface card = sdcard.SDCard(sd_spi, sd_cs) os.mount(card, '/sd') print(os.listdir('/sd')) # Only for debug purposes # Initialize the VS1053 module vs1053 = VS1053(co_spi, vs1053_cs, vs1053_dcs, vs1053_dreq, vs1053_reset) vs1053.init() vs1053.play_file("/sd/andrea.mp3") # Start netradio radioURL= "http://lyd.nrk.no/nrk_radio_klassisk_mp3_h?_hdr=0" nradio = netradio() nradio.connect_wifi("","") vs1053.play_stream(nradio.connect(radioURL))