#!/usr/bin/python
# -*- encoding: utf-8 -*-

# Priklad ovladani obvodu PCA9685: 
#  bzuceni reproduktorku pripojeneho pres PNP tranzistor na PWM0 (zvysovani frekvence)

import time
import smbus



bus = smbus.SMBus(1)   # novejsi varianta RasPi (512MB)
#bus = smbus.SMBus(0)   # starsi varianta RasPi (256MB)

addr = 0x40            # I2C adresa obvodu PCA9685 (kdyz jsou vsechny adresovaci vstupy v "0", je adresa 0x40)

gen=25000000                                   # frekvence vnitrniho generatoru obvodu PCA9685 (25MHz)
kanal = 0                                      # cislo kanalu na ktery je pripojeny reproduktorek 0 az 15

adr_kan = 6 + (kanal * 4)                      # kazdy kanal se ridi pomomci 4 bajtu. Nulty kanal zacina na adrese 6



bus.write_byte_data(addr,0x01,0b00010100)      # Logika vystupu obvodu: (INVRT=1, OUTDRV=1)

# hlavni smycka pro postupne zvysovani frekvence od 100Hz do 1,6kHz po kroku 300Hz
for frekvence in range (100,1600,300):

  n = int((gen / frekvence) / 4096)-1            # prepocet frekvence na pozadovanou konstantu prescaleru (orezava)
  nastavena_frekv = gen / (4096.0 * (n+1))       # zpetny vypocet skutecne nastavene frekvence
  print "Skutecne nastavena frekvence:  " + str(nastavena_frekv)  + " (prescaler (0 az 255): " + str(n) + ")"


  # inicializace PWM s pouzitim vnitrniho oscilatoru (25MHz)
  bus.write_byte_data(addr,0x00,0b00010000)  # SLEEP
  bus.write_byte_data(addr,0xFE,n)           # nastaveni frekvence prescaleru
  # nastaveni parametru jednoho kanalu na 50% stridy
  bus.write_byte_data(addr, adr_kan,     0) # prechod signalu z "0" na "1" v case "T + nula"  8xLSB
  bus.write_byte_data(addr, adr_kan + 1, 0) #                                                 4xMSB
  bus.write_byte_data(addr, adr_kan + 2, 0b00000000) #  cas prechodu z "1" na "0" 8xLSB
  bus.write_byte_data(addr, adr_kan + 3, 0b00001000) #                            4xMSB  (0b0100 00000000 = 50%)
  
  
  # spusteni generatoru na 2 sekundy    
  bus.write_byte_data(addr,0x00,0b00000000)  # spust PWM generator
  time.sleep(2)                              # 2 sekund generovani signalu
  

# z duvodu pouziti PNP spinaciho tranzistoru se reproduktorek vypina logickou "1"
bus.write_byte_data(addr, adr_kan + 3, 0b00010000) # bit 4 v "1" znamena Full ON (trvale sepnuti vystupu do "1")

