@@ -808,6 +808,235 @@ func (i2c I2C) readByte() byte {
808
808
return byte (i2c .Bus .DATA )
809
809
}
810
810
811
+ // I2S on the SAMD21.
812
+
813
+ // I2S
814
+ type I2S struct {
815
+ Bus * sam.I2S_Type
816
+ }
817
+
818
+ // Configure is used to configure the I2S interface. You must call this
819
+ // before you can use the I2S bus.
820
+ func (i2s I2S ) Configure (config I2SConfig ) {
821
+ // handle defaults
822
+ if config .SCK == 0 {
823
+ config .SCK = I2S_SCK_PIN
824
+ config .WS = I2S_WS_PIN
825
+ config .SD = I2S_SD_PIN
826
+ }
827
+
828
+ if config .AudioFrequency == 0 {
829
+ config .AudioFrequency = 48000
830
+ }
831
+
832
+ if config .DataFormat == I2SDataFormatDefault {
833
+ if config .Stereo {
834
+ config .DataFormat = I2SDataFormat16bit
835
+ } else {
836
+ config .DataFormat = I2SDataFormat32bit
837
+ }
838
+ }
839
+
840
+ // Turn on clock for I2S
841
+ sam .PM .APBCMASK |= sam .PM_APBCMASK_I2S_
842
+
843
+ // setting clock rate for sample.
844
+ division_factor := CPU_FREQUENCY / (config .AudioFrequency * uint32 (config .DataFormat ))
845
+
846
+ // Switch Generic Clock Generator 3 to DFLL48M.
847
+ sam .GCLK .GENDIV = sam .RegValue ((sam .GCLK_CLKCTRL_GEN_GCLK3 << sam .GCLK_GENDIV_ID_Pos ) |
848
+ (division_factor << sam .GCLK_GENDIV_DIV_Pos ))
849
+ waitForSync ()
850
+
851
+ sam .GCLK .GENCTRL = sam .RegValue ((sam .GCLK_CLKCTRL_GEN_GCLK3 << sam .GCLK_GENCTRL_ID_Pos ) |
852
+ (sam .GCLK_GENCTRL_SRC_DFLL48M << sam .GCLK_GENCTRL_SRC_Pos ) |
853
+ sam .GCLK_GENCTRL_IDC |
854
+ sam .GCLK_GENCTRL_GENEN )
855
+ waitForSync ()
856
+
857
+ // Use Generic Clock Generator 3 as source for I2S.
858
+ sam .GCLK .CLKCTRL = sam .RegValue16 ((sam .GCLK_CLKCTRL_ID_I2S_0 << sam .GCLK_CLKCTRL_ID_Pos ) |
859
+ (sam .GCLK_CLKCTRL_GEN_GCLK3 << sam .GCLK_CLKCTRL_GEN_Pos ) |
860
+ sam .GCLK_CLKCTRL_CLKEN )
861
+ waitForSync ()
862
+
863
+ // reset the device
864
+ i2s .Bus .CTRLA |= sam .I2S_CTRLA_SWRST
865
+ for (i2s .Bus .SYNCBUSY & sam .I2S_SYNCBUSY_SWRST ) > 0 {
866
+ }
867
+
868
+ // disable device before continuing
869
+ for (i2s .Bus .SYNCBUSY & sam .I2S_SYNCBUSY_ENABLE ) > 0 {
870
+ }
871
+ i2s .Bus .CTRLA &^= sam .I2S_CTRLA_ENABLE
872
+
873
+ // setup clock
874
+ if config .ClockSource == I2SClockSourceInternal {
875
+ // TODO: make sure correct for I2S output
876
+
877
+ // set serial clock select pin
878
+ i2s .Bus .CLKCTRL0 |= sam .I2S_CLKCTRL_SCKSEL
879
+
880
+ // set frame select pin
881
+ i2s .Bus .CLKCTRL0 |= sam .I2S_CLKCTRL_FSSEL
882
+ } else {
883
+ // Configure FS generation from SCK clock.
884
+ i2s .Bus .CLKCTRL0 &^= sam .I2S_CLKCTRL_FSSEL
885
+ }
886
+
887
+ if config .Standard == I2StandardPhilips {
888
+ // set 1-bit delay
889
+ i2s .Bus .CLKCTRL0 |= sam .I2S_CLKCTRL_BITDELAY
890
+ } else {
891
+ // set 0-bit delay
892
+ i2s .Bus .CLKCTRL0 &^= sam .I2S_CLKCTRL_BITDELAY
893
+ }
894
+
895
+ // set number of slots.
896
+ if config .Stereo {
897
+ i2s .Bus .CLKCTRL0 |= (1 << sam .I2S_CLKCTRL_NBSLOTS_Pos )
898
+ } else {
899
+ i2s .Bus .CLKCTRL0 &^= (1 << sam .I2S_CLKCTRL_NBSLOTS_Pos )
900
+ }
901
+
902
+ // set slot size
903
+ switch config .DataFormat {
904
+ case I2SDataFormat8bit :
905
+ i2s .Bus .CLKCTRL0 |= sam .I2S_CLKCTRL_SLOTSIZE_8
906
+
907
+ case I2SDataFormat16bit :
908
+ i2s .Bus .CLKCTRL0 |= sam .I2S_CLKCTRL_SLOTSIZE_16
909
+
910
+ case I2SDataFormat24bit :
911
+ i2s .Bus .CLKCTRL0 |= sam .I2S_CLKCTRL_SLOTSIZE_24
912
+
913
+ case I2SDataFormat32bit :
914
+ i2s .Bus .CLKCTRL0 |= sam .I2S_CLKCTRL_SLOTSIZE_32
915
+ }
916
+
917
+ // configure pin for clock
918
+ GPIO {config .SCK }.Configure (GPIOConfig {Mode : GPIO_COM })
919
+
920
+ // configure pin for WS, if needed
921
+ if config .WS != 0xff {
922
+ GPIO {config .WS }.Configure (GPIOConfig {Mode : GPIO_COM })
923
+ }
924
+
925
+ // now set serializer data size.
926
+ switch config .DataFormat {
927
+ case I2SDataFormat8bit :
928
+ i2s .Bus .SERCTRL1 |= sam .I2S_SERCTRL_DATASIZE_8
929
+
930
+ case I2SDataFormat16bit :
931
+ i2s .Bus .SERCTRL1 |= sam .I2S_SERCTRL_DATASIZE_16
932
+
933
+ case I2SDataFormat24bit :
934
+ i2s .Bus .SERCTRL1 |= sam .I2S_SERCTRL_DATASIZE_24
935
+
936
+ case I2SDataFormat32bit :
937
+ case I2SDataFormatDefault :
938
+ i2s .Bus .SERCTRL1 |= sam .I2S_SERCTRL_DATASIZE_32
939
+ }
940
+
941
+ // set serializer slot adjustment
942
+ if config .Standard == I2SStandardLSB {
943
+ // adjust right
944
+ i2s .Bus .SERCTRL1 &^= sam .I2S_SERCTRL_SLOTADJ
945
+ } else {
946
+ // adjust left
947
+ i2s .Bus .SERCTRL1 |= sam .I2S_SERCTRL_SLOTADJ
948
+
949
+ // reverse bit order?
950
+ i2s .Bus .SERCTRL1 |= sam .I2S_SERCTRL_BITREV
951
+ }
952
+
953
+ // set serializer mode.
954
+ if config .Mode == I2SModePDM {
955
+ i2s .Bus .SERCTRL1 |= sam .I2S_SERCTRL_SERMODE_PDM2
956
+ } else {
957
+ i2s .Bus .SERCTRL1 |= sam .I2S_SERCTRL_SERMODE_RX
958
+ }
959
+
960
+ // configure data pin
961
+ GPIO {config .SD }.Configure (GPIOConfig {Mode : GPIO_COM })
962
+
963
+ // re-enable
964
+ i2s .Bus .CTRLA |= sam .I2S_CTRLA_ENABLE
965
+ for (i2s .Bus .SYNCBUSY & sam .I2S_SYNCBUSY_ENABLE ) > 0 {
966
+ }
967
+
968
+ // enable i2s clock
969
+ i2s .Bus .CTRLA |= sam .I2S_CTRLA_CKEN0
970
+ for (i2s .Bus .SYNCBUSY & sam .I2S_SYNCBUSY_CKEN0 ) > 0 {
971
+ }
972
+
973
+ // enable i2s serializer
974
+ i2s .Bus .CTRLA |= sam .I2S_CTRLA_SEREN1
975
+ for (i2s .Bus .SYNCBUSY & sam .I2S_SYNCBUSY_SEREN1 ) > 0 {
976
+ }
977
+ }
978
+
979
+ // Read data from the I2S bus into the provided slice.
980
+ // The I2S bus must already have been configured correctly.
981
+ func (i2s I2S ) Read (p []uint32 ) (n int , err error ) {
982
+ i := 0
983
+ for i = 0 ; i < len (p ); i ++ {
984
+ // Wait until ready
985
+ for (i2s .Bus .INTFLAG & sam .I2S_INTFLAG_RXRDY1 ) == 0 {
986
+ }
987
+
988
+ for (i2s .Bus .SYNCBUSY & sam .I2S_SYNCBUSY_DATA1 ) > 0 {
989
+ }
990
+
991
+ // read data
992
+ p [i ] = uint32 (i2s .Bus .DATA1 )
993
+
994
+ // indicate read complete
995
+ i2s .Bus .INTFLAG = sam .I2S_INTFLAG_RXRDY1
996
+ }
997
+
998
+ return i , nil
999
+ }
1000
+
1001
+ // Write data to the I2S bus from the provided slice.
1002
+ // The I2S bus must already have been configured correctly.
1003
+ func (i2s I2S ) Write (p []uint32 ) (n int , err error ) {
1004
+ i := 0
1005
+ for i = 0 ; i < len (p ); i ++ {
1006
+ // Wait until ready
1007
+ for (i2s .Bus .INTFLAG & sam .I2S_INTFLAG_TXRDY1 ) == 0 {
1008
+ }
1009
+
1010
+ for (i2s .Bus .SYNCBUSY & sam .I2S_SYNCBUSY_DATA1 ) > 0 {
1011
+ }
1012
+
1013
+ // write data
1014
+ i2s .Bus .DATA1 = sam .RegValue (p [i ])
1015
+
1016
+ // indicate write complete
1017
+ i2s .Bus .INTFLAG = sam .I2S_INTFLAG_TXRDY1
1018
+ }
1019
+
1020
+ return i , nil
1021
+ }
1022
+
1023
+ // Close the I2S bus.
1024
+ func (i2s I2S ) Close () error {
1025
+ // Sync wait
1026
+ for (i2s .Bus .SYNCBUSY & sam .I2S_SYNCBUSY_ENABLE ) > 0 {
1027
+ }
1028
+
1029
+ // disable I2S
1030
+ i2s .Bus .CTRLA &^= sam .I2S_CTRLA_ENABLE
1031
+
1032
+ return nil
1033
+ }
1034
+
1035
+ func waitForSync () {
1036
+ for (sam .GCLK .STATUS & sam .GCLK_STATUS_SYNCBUSY ) > 0 {
1037
+ }
1038
+ }
1039
+
811
1040
// SPI
812
1041
type SPI struct {
813
1042
Bus * sam.SERCOM_SPI_Type
0 commit comments